|
@@ -0,0 +1,317 @@
|
|
|
|
+<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' scoped>
|
|
|
|
+ /* 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>
|