| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 | 
							- <template>
 
- 	<!-- #ifndef APP-NVUE -->
 
- 	<view
 
- 	    class="u-grid-item"
 
- 	    hover-class="u-grid-item--hover-class"
 
- 	    :hover-stay-time="200"
 
- 	    @tap="clickHandler"
 
- 	    :class="classes"
 
- 	    :style="[itemStyle]"
 
- 	>
 
- 		<slot />
 
- 	</view>
 
- 	<!-- #endif -->
 
- 	<!-- #ifdef APP-NVUE -->
 
- 	<view
 
- 	    class="u-grid-item"
 
- 	    :hover-stay-time="200"
 
- 	    @tap="clickHandler"
 
- 	    :class="classes"
 
- 	    :style="[itemStyle]"
 
- 	>
 
- 		<slot />
 
- 	</view>
 
- 	<!-- #endif -->
 
- </template>
 
- <script>
 
- 	import props from './props.js';
 
- 	/**
 
- 	 * gridItem 提示
 
- 	 * @description 宫格组件一般用于同时展示多个同类项目的场景,可以给宫格的项目设置徽标组件(badge),或者图标等,也可以扩展为左右滑动的轮播形式。搭配u-grid使用
 
- 	 * @tutorial https://www.uviewui.com/components/grid.html
 
- 	 * @property {String | Number}	name		宫格的name ( 默认 null )
 
- 	 * @property {String}			bgColor		宫格的背景颜色 (默认 'transparent' )
 
- 	 * @property {Object}			customStyle	自定义样式,对象形式
 
- 	 * @event {Function} click 点击宫格触发
 
- 	 * @example <u-grid-item></u-grid-item>
 
- 	 */
 
- 	export default {
 
- 		name: "u-grid-item",
 
- 		mixins: [uni.$u.mpMixin, uni.$u.mixin,props],
 
- 		data() {
 
- 			return {
 
- 				parentData: {
 
- 					col: 3, // 父组件划分的宫格数
 
- 					border: true, // 是否显示边框,根据父组件决定
 
- 				},
 
- 				// #ifdef APP-NVUE
 
- 				width: 0, // nvue下才这么计算,vue下放到computed中,否则会因为延时造成闪烁
 
- 				// #endif
 
- 				classes: [], // 类名集合,用于判断是否显示右边和下边框
 
- 			};
 
- 		},
 
- 		mounted() {
 
- 			this.init()
 
- 		},
 
- 		computed: {
 
- 			// #ifndef APP-NVUE
 
- 			// vue下放到computed中,否则会因为延时造成闪烁
 
- 			width() {
 
- 				return 100 / Number(this.parentData.col) + '%'
 
- 			},
 
- 			// #endif
 
- 			itemStyle() {
 
- 				const style = {
 
- 					background: this.bgColor,
 
- 					width: this.width
 
- 				}
 
- 				return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle))
 
- 			}
 
- 		},
 
- 		methods: {
 
- 			init() {
 
- 				// 用于在父组件u-grid的children中被添加入子组件时,
 
- 				// 重新计算item的边框
 
- 				uni.$on('$uGridItem', () => {
 
- 					this.gridItemClasses()
 
- 				})
 
- 				// 父组件的实例
 
- 				this.updateParentData()
 
- 				// #ifdef APP-NVUE
 
- 				// 获取元素该有的长度,nvue下要延时才准确
 
- 				this.$nextTick(function(){
 
- 					this.getItemWidth()
 
- 				})
 
- 				// #endif
 
- 				// 发出事件,通知所有的grid-item都重新计算自己的边框
 
- 				uni.$emit('$uGridItem')
 
- 				this.gridItemClasses()
 
- 			},
 
- 			// 获取父组件的参数
 
- 			updateParentData() {
 
- 				// 此方法写在mixin中
 
- 				this.getParentData('u-grid');
 
- 			},
 
- 			clickHandler() {
 
- 				let name = this.name
 
- 				// 如果没有设置name属性,历遍父组件的children数组,判断当前的元素是否和本实例this相等,找出当前组件的索引
 
- 				const children = this.parent?.children
 
- 				if(children && this.name === null) {
 
- 					name = children.findIndex(child => child === this)
 
- 				}
 
- 				// 调用父组件方法,发出事件
 
- 				this.parent && this.parent.childClick(name)
 
- 				this.$emit('click', name)
 
- 			},
 
- 			async getItemWidth() {
 
- 				// 如果是nvue,不能使用百分比,只能使用固定宽度
 
- 				let width = 0
 
- 				if(this.parent) {
 
- 					// 获取父组件宽度后,除以栅格数,得出每个item的宽度
 
- 					const parentWidth = await this.getParentWidth()
 
- 					width = parentWidth / Number(this.parentData.col) + 'px'
 
- 				}
 
- 				this.width = width
 
- 			},
 
- 			// 获取父元素的尺寸
 
- 			getParentWidth() {
 
- 				// #ifdef APP-NVUE
 
- 				// 返回一个promise,让调用者可以用await同步获取
 
- 				const dom = uni.requireNativePlugin('dom')
 
- 				return new Promise(resolve => {
 
- 					// 调用父组件的ref
 
- 					dom.getComponentRect(this.parent.$refs['u-grid'], res => {
 
- 						resolve(res.size.width)
 
- 					})
 
- 				})
 
- 				// #endif
 
- 			},
 
- 			gridItemClasses() {
 
- 				if(this.parentData.border) {
 
- 					const classes = []
 
- 					this.parent.children.map((child, index) =>{
 
- 						if(this === child) {
 
- 							const len = this.parent.children.length
 
- 							// 贴近右边屏幕边沿的child,并且最后一个(比如只有横向2个的时候),无需右边框
 
- 							if((index + 1) % this.parentData.col !== 0 && index + 1 !== len) {
 
- 								classes.push('u-border-right')
 
- 							}
 
- 							// 总的宫格数量对列数取余的值
 
- 							// 如果取余后,值为0,则意味着要将最后一排的宫格,都不需要下边框
 
- 							const lessNum = len % this.parentData.col === 0 ? this.parentData.col : len % this.parentData.col
 
- 							// 最下面的一排child,无需下边框
 
- 							if(index < len - lessNum) {
 
- 								classes.push('u-border-bottom')
 
- 							}
 
- 						}
 
- 					})
 
- 					// 支付宝,头条小程序无法动态绑定一个数组类名,否则解析出来的结果会带有",",而导致失效
 
- 					// #ifdef MP-ALIPAY || MP-TOUTIAO
 
- 					classes = classes.join(' ')
 
- 					// #endif
 
- 					this.classes = classes
 
- 				}
 
- 			}
 
- 		},
 
- 		beforeDestroy() {
 
- 			// 移除事件监听,释放性能
 
- 			uni.$off('$uGridItem')
 
- 		}
 
- 	};
 
- </script>
 
- <style lang="scss" scoped>
 
- 	@import "../../libs/css/components.scss";
 
-       $u-grid-item-hover-class-opcatiy:.5 !default;
 
-       $u-grid-item-margin-top:1rpx !default;
 
-       $u-grid-item-border-right-width:0.5px !default;
 
-       $u-grid-item-border-bottom-width:0.5px !default;
 
-       $u-grid-item-border-right-color:$u-border-color !default;
 
-       $u-grid-item-border-bottom-color:$u-border-color !default;
 
- 	.u-grid-item {
 
- 		align-items: center;
 
- 		justify-content: center;
 
- 		position: relative;
 
- 		flex-direction: column;
 
- 		/* #ifndef APP-NVUE */
 
- 		box-sizing: border-box;
 
- 		display: flex;
 
- 		/* #endif */
 
- 		/* #ifdef MP */
 
- 		position: relative;
 
- 		float: left;
 
- 		/* #endif */
 
- 		/* #ifdef MP-WEIXIN */
 
- 		margin-top:$u-grid-item-margin-top;
 
- 		/* #endif */
 
- 		&--hover-class {
 
- 			opacity:$u-grid-item-hover-class-opcatiy;
 
- 		}
 
- 	}
 
- 	/* #ifdef APP-NVUE */
 
- 	// 由于nvue不支持组件内引入app.vue中再引入的样式,所以需要写在这里
 
- 	.u-border-right {
 
- 		border-right-width:$u-grid-item-border-right-width;
 
- 		border-color: $u-grid-item-border-right-color;
 
- 	}
 
- 	.u-border-bottom {
 
- 		border-bottom-width:$u-grid-item-border-bottom-width;
 
- 		border-color:$u-grid-item-border-bottom-color;
 
- 	}
 
- 	/* #endif */
 
- </style>
 
 
  |