08335 / hivui-platform-template
hivui平台项目模板
Newer
Older
hivui-platform-template / project / hivuiMain / components / grid / row.vue
caibinghong on 4 Jun 2021 add
<template>
  <div :class="classes" :style="rowStyle">
    <slot></slot>
  </div>
</template>
<script>
import PropTypes from '@main/utils/vue-types/index'
import enquire from 'enquire.js'
// matchMedia polyfill for
// https://github.com/WickyNilliams/enquire.js/issues/82
// let enquire = null;
if (typeof window !== "undefined") {
    const matchMediaPolyfill = mediaQuery => {
        return {
            media: mediaQuery,
            matches: false,
            addListener() {},
            removeListener() {}
        };
    };
    window.matchMedia = window.matchMedia || matchMediaPolyfill;
    // enquire = require("enquire.js");
}

const BreakpointMap = PropTypes.shape({
    xs: PropTypes.number,
    sm: PropTypes.number,
    md: PropTypes.number,
    lg: PropTypes.number,
    xl: PropTypes.number,
    xxl: PropTypes.number
}).loose;

const RowProps = {
  gutter: PropTypes.oneOfType([PropTypes.number, BreakpointMap]),
  type: PropTypes.oneOf(["flex"]),
  align: PropTypes.oneOf(["top", "middle", "bottom"]),
  justify: PropTypes.oneOf([
    "start",
    "end",
    "center",
    "space-around",
    "space-between"
  ]),
  prefixCls: PropTypes.string
};

const responsiveArray = ["xxl", "xl", "lg", "md", "sm", "xs"];
const responsiveMap = {
  xs: "(max-width: 575px)",
  sm: "(min-width: 576px)",
  md: "(min-width: 768px)",
  lg: "(min-width: 992px)",
  xl: "(min-width: 1200px)",
  xxl: "(min-width: 1600px)"
};

export default {
    name: "pl-row",
    //mixins: [BaseMixin],
    props: {
        ...RowProps,
        gutter: PropTypes.oneOfType([PropTypes.number, BreakpointMap]).def(0)
    },
    provide() {
        return {
            rowContext: this
        };
    },
    data() {
        return {
            screens: {}
        };
    },
    computed:{
        classes(){
            const { type, justify, align, prefixCls = "pl-row", $slots } = this;
            const classes = {
                [prefixCls]: !type,
                [`${prefixCls}-${type}`]: type,
                [`${prefixCls}-${type}-${justify}`]: type && justify,
                [`${prefixCls}-${type}-${align}`]: type && align
            };
            return classes;
        },
        rowStyle(){
            const gutter = this.getGutter();
            const rowStyle =
                gutter > 0
                ? {
                    marginLeft: `${gutter / -2}px`,
                    marginRight: `${gutter / -2}px`
                    }
                : {};
            return rowStyle;
        }
    },
    mounted() {
        this.$nextTick(() => {
            Object.keys(responsiveMap).map(screen =>{
                enquire.register(responsiveMap[screen], {
                    match: () => {
                    if (typeof this.gutter !== "object") {
                        return;
                    }
                    this.setState(prevState => ({
                        screens: {
                            ...prevState.screens,
                            [screen]: true
                        }
                    }));
                    },
                    unmatch: () => {
                    if (typeof this.gutter !== "object") {
                        return;
                    }
                    this.setState(prevState => ({
                        screens: {
                        ...prevState.screens,
                        [screen]: false
                        }
                    }));
                    },
                    // Keep a empty destory to avoid triggering unmatch when unregister
                    destroy() {}
                })
            });
        });
    },
    beforeDestroy() {
        Object.keys(responsiveMap).map(screen =>
            enquire.unregister(responsiveMap[screen])
        );
    },
    
    methods: {
        setState(state, callback) {
            const newState = typeof state === 'function' ? state(this.$data, this.$props) : state;
            Object.assign(this.$data, newState);
            this.$nextTick(() => {
                callback && callback();
            });
        },
        __emit() {
            // 直接调用listeners,底层组件不需要vueTool记录events
            const args = [].slice.call(arguments, 0);
            const filterEvent = [];
            const eventName = args[0];
            if (args.length && this.$listeners[eventName]) {
                if (filterEvent.includes(eventName)) {
                this.$emit(eventName, ...args.slice(1));
                } else {
                this.$listeners[eventName](...args.slice(1));
                }
            }
        },
        getGutter() {
            const { gutter } = this;
            if (typeof gutter === "object") {
                for (let i = 0; i < responsiveArray.length; i++) {
                    const breakpoint = responsiveArray[i];
                    if (this.screens[breakpoint] && gutter[breakpoint] !== undefined) {
                    return gutter[breakpoint];
                    }
                }
            }
            return gutter;
        }
    }
};
</script>