You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							317 lines
						
					
					
						
							7.5 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							317 lines
						
					
					
						
							7.5 KiB
						
					
					
				
								<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>
							 |