<template> 
 | 
    <!-- #ifndef APP-NVUE --> 
 | 
    <view :class="['uni-col', sizeClass, pointClassList]" :style="{ 
 | 
        paddingLeft:`${Number(gutter)}rpx`, 
 | 
        paddingRight:`${Number(gutter)}rpx`, 
 | 
    }"> 
 | 
        <slot></slot> 
 | 
    </view> 
 | 
    <!-- #endif --> 
 | 
    <!-- #ifdef APP-NVUE --> 
 | 
    <!-- 在nvue上,类名样式不生效,换为style --> 
 | 
    <!-- 设置right正值失效,设置 left 负值 --> 
 | 
    <view :class="['uni-col']" :style="{ 
 | 
        paddingLeft:`${Number(gutter)}rpx`, 
 | 
        paddingRight:`${Number(gutter)}rpx`, 
 | 
        width:`${nvueWidth}rpx`, 
 | 
        position:'relative', 
 | 
        marginLeft:`${marginLeft}rpx`, 
 | 
        left:`${right === 0 ? left : -right}rpx` 
 | 
    }"> 
 | 
        <slot></slot> 
 | 
    </view> 
 | 
    <!-- #endif --> 
 | 
</template> 
 | 
  
 | 
<script> 
 | 
    /** 
 | 
     * Col    布局-列 
 | 
     * @description    搭配uni-row使用,构建布局。 
 | 
     * @tutorial    https://ext.dcloud.net.cn/plugin?id=3958 
 | 
     * 
 | 
     * @property    {span} type = Number 栅格占据的列数 
 | 
     *                         默认 24 
 | 
     * @property    {offset} type = Number 栅格左侧的间隔格数 
 | 
     * @property    {push} type = Number 栅格向右移动格数 
 | 
     * @property    {pull} type = Number 栅格向左移动格数 
 | 
     * @property    {xs} type = [Number, Object] <768px 响应式栅格数或者栅格属性对象 
 | 
     *                         @description    Number时表示在此屏幕宽度下,栅格占据的列数。Object时可配置多个描述{span: 4, offset: 4} 
 | 
     * @property    {sm} type = [Number, Object] ≥768px 响应式栅格数或者栅格属性对象 
 | 
     *                         @description    Number时表示在此屏幕宽度下,栅格占据的列数。Object时可配置多个描述{span: 4, offset: 4} 
 | 
     * @property    {md} type = [Number, Object] ≥992px 响应式栅格数或者栅格属性对象 
 | 
     *                         @description    Number时表示在此屏幕宽度下,栅格占据的列数。Object时可配置多个描述{span: 4, offset: 4} 
 | 
     * @property    {lg} type = [Number, Object] ≥1200px 响应式栅格数或者栅格属性对象 
 | 
     *                         @description    Number时表示在此屏幕宽度下,栅格占据的列数。Object时可配置多个描述{span: 4, offset: 4} 
 | 
     * @property    {xl} type = [Number, Object] ≥1920px 响应式栅格数或者栅格属性对象 
 | 
     *                         @description    Number时表示在此屏幕宽度下,栅格占据的列数。Object时可配置多个描述{span: 4, offset: 4} 
 | 
     */ 
 | 
    const ComponentClass = 'uni-col'; 
 | 
  
 | 
    // -1 默认值,因为在微信小程序端只给Number会有默认值0 
 | 
    export default { 
 | 
        name: 'uniCol', 
 | 
        // #ifdef MP-WEIXIN 
 | 
        options: { 
 | 
            virtualHost: true // 在微信小程序中将组件节点渲染为虚拟节点,更加接近Vue组件的表现 
 | 
        }, 
 | 
        // #endif 
 | 
        props: { 
 | 
            span: { 
 | 
                type: Number, 
 | 
                default: 24 
 | 
            }, 
 | 
            offset: { 
 | 
                type: Number, 
 | 
                default: -1 
 | 
            }, 
 | 
            pull: { 
 | 
                type: Number, 
 | 
                default: -1 
 | 
            }, 
 | 
            push: { 
 | 
                type: Number, 
 | 
                default: -1 
 | 
            }, 
 | 
            xs: [Number, Object], 
 | 
            sm: [Number, Object], 
 | 
            md: [Number, Object], 
 | 
            lg: [Number, Object], 
 | 
            xl: [Number, Object] 
 | 
        }, 
 | 
        data() { 
 | 
            return { 
 | 
                gutter: 0, 
 | 
                sizeClass: '', 
 | 
                parentWidth: 0, 
 | 
                nvueWidth: 0, 
 | 
                marginLeft: 0, 
 | 
                right: 0, 
 | 
                left: 0 
 | 
            } 
 | 
        }, 
 | 
        created() { 
 | 
            // 字节小程序中,在computed中读取$parent为undefined 
 | 
            let parent = this.$parent; 
 | 
  
 | 
            while (parent && parent.$options.componentName !== 'uniRow') { 
 | 
                parent = parent.$parent; 
 | 
            } 
 | 
  
 | 
            this.updateGutter(parent.gutter) 
 | 
            parent.$watch('gutter', (gutter) => { 
 | 
                this.updateGutter(gutter) 
 | 
            }) 
 | 
  
 | 
            // #ifdef APP-NVUE 
 | 
            this.updateNvueWidth(parent.width) 
 | 
            parent.$watch('width', (width) => { 
 | 
                this.updateNvueWidth(width) 
 | 
            }) 
 | 
            // #endif 
 | 
        }, 
 | 
        computed: { 
 | 
            sizeList() { 
 | 
                let { 
 | 
                    span, 
 | 
                    offset, 
 | 
                    pull, 
 | 
                    push 
 | 
                } = this; 
 | 
  
 | 
                return { 
 | 
                    span, 
 | 
                    offset, 
 | 
                    pull, 
 | 
                    push 
 | 
                } 
 | 
            }, 
 | 
            // #ifndef APP-NVUE 
 | 
            pointClassList() { 
 | 
                let classList = []; 
 | 
  
 | 
                ['xs', 'sm', 'md', 'lg', 'xl'].forEach(point => { 
 | 
                    const props = this[point]; 
 | 
                    if (typeof props === 'number') { 
 | 
                        classList.push(`${ComponentClass}-${point}-${props}`) 
 | 
                    } else if (typeof props === 'object' && props) { 
 | 
                        Object.keys(props).forEach(pointProp => { 
 | 
                            classList.push( 
 | 
                                pointProp === 'span' ? 
 | 
                                `${ComponentClass}-${point}-${props[pointProp]}` : 
 | 
                                `${ComponentClass}-${point}-${pointProp}-${props[pointProp]}` 
 | 
                            ) 
 | 
                        }) 
 | 
                    } 
 | 
                }); 
 | 
  
 | 
                // 支付宝小程序使用 :class=[ ['a','b'] ],渲染错误 
 | 
                return classList.join(' '); 
 | 
            } 
 | 
            // #endif 
 | 
        }, 
 | 
        methods: { 
 | 
            updateGutter(parentGutter) { 
 | 
                parentGutter = Number(parentGutter); 
 | 
                if (!isNaN(parentGutter)) { 
 | 
                    this.gutter = parentGutter / 2 
 | 
                } 
 | 
            }, 
 | 
            // #ifdef APP-NVUE 
 | 
            updateNvueWidth(width) { 
 | 
                // 用于在nvue端,span,offset,pull,push的计算 
 | 
                this.parentWidth = width; 
 | 
                ['span', 'offset', 'pull', 'push'].forEach(size => { 
 | 
                    const curSize = this[size]; 
 | 
                    if ((curSize || curSize === 0) && curSize !== -1) { 
 | 
                        let RPX = 1 / 24 * curSize * width 
 | 
                        RPX = Number(RPX); 
 | 
                        switch (size) { 
 | 
                            case 'span': 
 | 
                                this.nvueWidth = RPX 
 | 
                                break; 
 | 
                            case 'offset': 
 | 
                                this.marginLeft = RPX 
 | 
                                break; 
 | 
                            case 'pull': 
 | 
                                this.right = RPX 
 | 
                                break; 
 | 
                            case 'push': 
 | 
                                this.left = RPX 
 | 
                                break; 
 | 
                        } 
 | 
                    } 
 | 
                }); 
 | 
            } 
 | 
            // #endif 
 | 
        }, 
 | 
        watch: { 
 | 
            sizeList: { 
 | 
                immediate: true, 
 | 
                handler(newVal) { 
 | 
                    // #ifndef APP-NVUE 
 | 
                    let classList = []; 
 | 
                    for (let size in newVal) { 
 | 
                        const curSize = newVal[size]; 
 | 
                        if ((curSize || curSize === 0) && curSize !== -1) { 
 | 
                            classList.push( 
 | 
                                size === 'span' ? 
 | 
                                `${ComponentClass}-${curSize}` : 
 | 
                                `${ComponentClass}-${size}-${curSize}` 
 | 
                            ) 
 | 
                        } 
 | 
                    } 
 | 
                    // 支付宝小程序使用 :class=[ ['a','b'] ],渲染错误 
 | 
                    this.sizeClass = classList.join(' '); 
 | 
                    // #endif 
 | 
                    // #ifdef APP-NVUE 
 | 
                    this.updateNvueWidth(this.parentWidth); 
 | 
                    // #endif 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
</script> 
 | 
  
 | 
<style lang='scss' > 
 | 
    /* breakpoints */ 
 | 
    $--sm: 768px !default; 
 | 
    $--md: 992px !default; 
 | 
    $--lg: 1200px !default; 
 | 
    $--xl: 1920px !default; 
 | 
  
 | 
    $breakpoints: ('xs' : (max-width: $--sm - 1), 
 | 
    'sm' : (min-width: $--sm), 
 | 
    'md' : (min-width: $--md), 
 | 
    'lg' : (min-width: $--lg), 
 | 
    'xl' : (min-width: $--xl)); 
 | 
  
 | 
    $layout-namespace: ".uni-"; 
 | 
    $col: $layout-namespace+"col"; 
 | 
  
 | 
    @function getSize($size) { 
 | 
        /* TODO 1/24 * $size * 100 * 1%; 使用计算后的值,为了解决 vue3 控制台报错 */ 
 | 
        @return 0.04166666666 * $size * 100 * 1%; 
 | 
    } 
 | 
  
 | 
    @mixin res($key, $map:$breakpoints) { 
 | 
        @if map-has-key($map, $key) { 
 | 
            @media screen and #{inspect(map-get($map,$key))} { 
 | 
                @content; 
 | 
            } 
 | 
        } 
 | 
  
 | 
        @else { 
 | 
            @warn "Undeinfed point: `#{$key}`"; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    /* #ifndef APP-NVUE */ 
 | 
    #{$col} { 
 | 
        float: left; 
 | 
        box-sizing: border-box; 
 | 
    } 
 | 
  
 | 
    #{$col}-0 { 
 | 
        /* #ifdef APP-NVUE */ 
 | 
        width: 0; 
 | 
        height: 0; 
 | 
        margin-top: 0; 
 | 
        margin-right: 0; 
 | 
        margin-bottom: 0; 
 | 
        margin-left: 0; 
 | 
        /* #endif */ 
 | 
        /* #ifndef APP-NVUE */ 
 | 
        display: none; 
 | 
        /* #endif */ 
 | 
    } 
 | 
  
 | 
    @for $i from 0 through 24 { 
 | 
        #{$col}-#{$i} { 
 | 
            width: getSize($i); 
 | 
        } 
 | 
  
 | 
        #{$col}-offset-#{$i} { 
 | 
            margin-left: getSize($i); 
 | 
        } 
 | 
  
 | 
        #{$col}-pull-#{$i} { 
 | 
            position: relative; 
 | 
            right: getSize($i); 
 | 
        } 
 | 
  
 | 
        #{$col}-push-#{$i} { 
 | 
            position: relative; 
 | 
            left: getSize($i); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    @each $point in map-keys($breakpoints) { 
 | 
        @include res($point) { 
 | 
            #{$col}-#{$point}-0 { 
 | 
                display: none; 
 | 
            } 
 | 
  
 | 
            @for $i from 0 through 24 { 
 | 
                #{$col}-#{$point}-#{$i} { 
 | 
                    width: getSize($i); 
 | 
                } 
 | 
  
 | 
                #{$col}-#{$point}-offset-#{$i} { 
 | 
                    margin-left: getSize($i); 
 | 
                } 
 | 
  
 | 
                #{$col}-#{$point}-pull-#{$i} { 
 | 
                    position: relative; 
 | 
                    right: getSize($i); 
 | 
                } 
 | 
  
 | 
                #{$col}-#{$point}-push-#{$i} { 
 | 
                    position: relative; 
 | 
                    left: getSize($i); 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    /* #endif */ 
 | 
</style> 
 |