赞
踩
技术栈:uniapp的vue3+vite2+ts版本
前言:在uview中没有列表相关的组件,对于有很多页面都是差不多类似于列表的,为了复用性比较高,所以自己封装了一个列表(list)组件
列表分为左/中/右三个部分,分别对应标题/内容/操作,通过props将父组件定义的内容传进来,可设置宽度、行与行的间距、颜色、外边距等,通过作用域插槽也可以进行每行的内容自定义
由于微信小程序不支持插槽默认值,所以通过按环境编译结合v-if实现功能,H5中支持插槽默认值直接使用即可
<template> <view class="info"> <view class="info-item" v-for="(item, index) in listField" :key="index" :style="{ '--margin-bottom': marginBottom }"> <view class="item-title" :style="titleStyle"> <!-- 左侧标题 --> <slot name="type">{{ item.value }}</slot> </view> <view class="item-content" :style="contentStyle"> <!-- 中间内容 --> <view class="item-text"> <!-- #ifdef MP-WEIXIN --> <view class="slot" v-if="item.isObj"> <slot :key="String(item.key)" :value="listData[item.key]" name="current"></slot> </view> <view v-else> {{ item.isPrice ? '¥' + listData[item.key] : listData[item.key] }} </view> <!-- #endif --> <!-- #ifdef H5 --> <slot :key="String(item.key)" :value="listData[item.key]" name="current"> <view :style="{ 'width': item.width ? item.width : '' }">{{ item.isPrice ? '¥' + listData[item.key] : listData[item.key] }}</view> </slot> <!-- #endif --> </view> </view> <view class="item-action"> <!-- 右侧标签及操作 --> <slot :key="String(item.key)" :value="listData[item.key]" name="action"></slot> </view> </view> </view> </template> <script lang='ts' setup> import { ref, reactive, computed, onMounted } from 'vue' /** * @titleStyle 标题样式 * @listData 数据列表 * @contentStyle 标题右侧内容样式 * @marginBottom item间距 * @listField 字段名称,用于生成列表结构,必须有key/value */ const props = defineProps( ['listData', 'listField', 'titleStyle', 'contentStyle', "marginBottom"] ) </script> <style lang='scss' scoped> .info { margin: 0 auto; .info-item { display: flex; position: relative; .item-title { text-align: right; min-width: 180rpx; padding-right: 10rpx; } .item-content { max-width: 450rpx; display: flex; align-items: flex-end; } .item-action { position: absolute; right: 0; } } .info-item:not(:last-child) { margin-bottom: var(--margin-bottom); } } .slot:empty { display: none; } </style>
此处使用包含了宽度、颜色、行与行间距、每行自定义等内容,可自行对照进行参照,根据所需进行修改
<template> <view class="content-box"> <list v-for="(item, index) in listData" :key="index" :listField="listField" :titleStyle="titleStyle" :marginBottom="marginBottom" :listData="item"> <template #current="{ key, value }"> <view v-if="key === 'address'"> {{ value.people }}<br>{{ value.detail }} </view> </template> <template #action="{ key, value }"> <!-- <u-icon name="copy" v-if="key === 'orderNo'" custom-prefix="custom-icon" size="25"></u-icon> --> <view v-if="key === 'serviceRrmark'" @click="handleClickAction">联系客服</view> </template> </list> </view> </template> <script lang='ts' setup> import { ref, reactive, computed, onMounted } from 'vue' import list from '@/components/list/index.vue' const listData = [{ id: 'SN3765456783764', createTime: '2022-07-10 17:00', address: { people: '某先生 13512345678', detail: '浙江省 杭州市 西湖区xxx路xx小区' }, totalprice: '1099', serviceRrmark: '该商品将通过顺丰快递发放,请注意查收' }] const listField = [ { key: 'id', value: '编号' }, { key: 'createTime', value: '时间' }, { key: 'address', value: '收货地址', isObj: true }, { key: 'totalprice', value: '商品总额', isPrice: true }, { key: 'serviceRrmark', value: '客服备注', width: '400rpx' }, ] const titleStyle = { minWidth: '110rpx', color: 'Green' } const marginBottom = '20rpx' const handleClickAction = () => { console.log('执行了此处的方法') } </script> <style lang='scss' scoped> .content-box { margin: 30rpx 40rpx; } </style>
1、关于微信小程序不支持slot默认值得讨论:https://developers.weixin.qq.com/community/develop/doc/0008a04f2b0f289fa907b450b56000
2、另一种解决方案,使用:empty伪类来解决,但是我测试后有局限性,不适合我需要的情况,但是也是个思路:https://blog.csdn.net/weixin_45747310/article/details/122305928
3、文章上述内容的demo案例,我放在了gitee上,有需要自行提取,若有用并且方便的话请收藏点赞一下,谢谢:https://gitee.com/zasulan/csdn-item/tree/master/uni-demo-item-vite
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。