赞
踩
在使用ant-design-vue中曾经使用过table组件,所以想着自己封装一个组件尝试一下,这是一个简易版本
封装一个名为Ttablede组件,该组件接收两个参数,分别是columns和dataSource
子组件:接收父组件传入的参数,并将传入的参数进行处理,提取出slot插槽值,用于动态设置具名插槽 import {computed, defineProps} from "vue"; // 接收参数 columns,dataSource const props = defineProps({ columns: { type: Array }, dataSource: { type: Array } }) // 提取slot属性,用于设置具名插槽 ref: columnSlot = computed(() => { const filterColumns = props.columns.length && props.columns.map((v) => { return v.slot }) return filterColumns })
const columns = [ { title: '变化信息', key: 'changeMsg', slot: 'changeMsg', }, { title: '当前出价', key: 'currentPrice', slot: 'currentPrice', }, { title: '最低出价', key: 'lowestPrice', slot: 'lowestPrice', }, { title: '最高出价', key: 'highestPrice', slot: 'highestPrice', }, ]
const dataList = [ { changeMsg:'课程词1', currentPrice:'1.11', lowestPrice:'0.01', highestPrice:'2.35', }, { changeMsg:'课程词2', currentPrice:'2.22', lowestPrice:'1.01', highestPrice:'3.35', }, { changeMsg:'课程词3', currentPrice:'3.33', lowestPrice:'3.01', highestPrice:'2.35', }, ]
<TTable
:columns="columns"
:dataSource="dataList"
>
</TTable>
<!--header-->
<li class="ttable-item header">
<p class="ttable-item-content" v-for="item in columns" :key="item.key">{{ item.title }}</p>
</li>
<!--content-->
<li class="ttable-item" v-for="(item,index) in dataSource" :key="index">
<p class="ttable-item-content" v-for="(it,idx) in columnSlot" :key="idx">
<slot :content="item" :name="it"/> // name动态设置具名插槽,content对应的数据传给外部父组件
</p>
</li>
<TTable :columns="columns" :dataSource="dataList" > <template v-slot:changeMsg="{content}" > // 具名插槽,接收对应的content的值 {{content.changeMsg}} </template> <template v-slot:currentPrice="{content}"> {{content.currentPrice}} </template> <template v-slot:lowestPrice="{content}"> {{content.lowestPrice}} </template> <template v-slot:highestPrice="{content}"> {{content.highestPrice}} </template> </TTable>
<!-- 功能:公共组件-table 时间:2021-04-23 madeBy:FTT --> <template> <ul class="ttable"> <!--横向分类--> <li class="ttable-item header"> <p class="ttable-item-content" v-for="item in columns" :key="item.key">{{ item.title }}</p> </li> <!--内容--> <li class="ttable-item" v-for="(item,index) in dataSource" :key="index"> <p class="ttable-item-content" v-for="(it,idx) in columnSlot" :key="idx"> <slot :content="item" :name="it"/> </p> </li> </ul> </template> <style scoped lang="less"> .ttable { padding: 10px 16px; .header { margin-bottom: 8px; } &-item { display: flex; justify-content: space-between; margin-bottom: 4px; &-content { flex: 1; } } } </style> <script setup> import {computed, defineProps} from "vue"; const props = defineProps({ columns: { type: Array }, dataSource: { type: Array } }) ref: columnSlot = computed(() => { const filterColumns = props.columns.length && props.columns.map((v) => { return v.slot }) return filterColumns }) </script>
<TTable :columns="columns" :dataSource="dataList" > <template v-slot:changeMsg="{content}" > {{content.changeMsg}} </template> <template v-slot:currentPrice="{content}"> {{content.currentPrice}} </template> <template v-slot:lowestPrice="{content}"> <span class="campaignItem-canChangeNum-style">{{content.lowestPrice}}</span> </template> <template v-slot:highestPrice="{content}"> <span class="campaignItem-canChangeNum-style">{{content.highestPrice}}</span> </template> </TTable> <style scoped lang="less"> .campaignItem-canChangeNum-style { color: #0085F8; text-decoration: underline; } </style> 其中columns可以自定义,dataList可以通过网络请求获取 import TTable from '../../components/common/TTable.vue';
样式可以根据需求进行调整
如上图所示,我们想要对蓝色部位进行动态修改,点击蓝色,可以编辑,失去焦点,保存内容并发送网络请求,对父组件代码进行修改
<template v-slot:lowestPrice="{content}"> <span @click="changeLowestVal(content)" v-if="!content.change" class="campaignItem-canChangeNum-style" > {{ content.lowestPrice }} </span> <van-field @blur="saveNewLowestVal(content)" v-else v-model="willChangeLowestVal"/> </template> <script setup> ref: willChangeLowestVal = ''; // 修改表格内容 async function changeLowestVal(content) { content.change = !content.change // 修改时,显示field组件 willChangeLowestVal = content.lowestPrice // 输入内容,赋值给willChangeLowestVal } // 保存表单修改内容 async function saveNewLowestVal(content) { // TODO: 可以在这里发送网络请求,将数据在远端保存 content.lowestPrice = willChangeLowestVal; // 保存表单内容,并在页面直接更新,避免整个页面的刷新体验不好 content.change = !content.change // 关闭field框,显示保存后的数据 } // 在初始化时对于可以修改的数据进行一个标识,不同的字段可以定义不同的change onMounted(() => { dataList.forEach((v) => { v.change = false; }) }) </script>
点击红框
修改红框的值
点击其他位置,令其失去焦点
如果觉得上述情况下,无法直接弹出键盘,也可以直接封装一个指令,在mounted时,获取焦点即可
增加一个选项loading
loading:{
type:Boolean,
default:false,
}
根据传入的loading值,判断展示列表还是loading选项
<template v-if="loading"> <van-loading type="spinner" color="#1989fa" vertical>加载中...</van-loading> </template> <!--内容--> <template v-else> <template v-if="dataSource.length"> <li class="ttable-item" v-for="(item,index) in dataSource" :key="index"> <p class="ttable-item-content" v-for="(it,idx) in columnSlot" :key="idx"> <slot :content="item" :name="it"/> </p> </li> </template> <template v-else> <TTableNull /> </template> </template>
外部传入的loading可以根据网络请求进行判断,若发送网络请求中,loading值传true,网络请求结束/出错,loading传false try…catch…finally 可以实现这种判断情形。
加载数据时效果
数据加载结束后的效果
如果有帮助的话,点个赞呗~
商用转载请标明来源哦~
总结用法,希望可以帮助到你,
我是Ably,你无须超越谁,只要超越昨天的自己就好~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。