123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- <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>
|