| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 | <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会有默认值0export 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>
 |