Vue3-封装table组件
在使用ant-design-vue中曾经使用过table组件,所以想着自己封装一个组件尝试一下,这是一个简易版本1. 相关知识点组件传值插槽(具名插槽、作用域插槽)vue3 setup2.封装子组件,按照要求规定参数封装一个名为Ttablede组件,该组件接收两个参数,分别是columns和dataSource2.1 子组件:接收参数,按数据提取动态具名插槽名子组件:接收父组件传入的参数,并将传入
·
在使用ant-design-vue中曾经使用过table组件,所以想着自己封装一个组件尝试一下,这是一个简易版本
1. 相关知识点
- 组件传值
- 插槽(具名插槽、作用域插槽)
- vue3 setup
- vant v3 部分组件使用
2.封装子组件,按照要求规定参数
封装一个名为Ttablede组件,该组件接收两个参数,分别是columns和dataSource
2.1 子组件:接收参数,按数据提取动态具名插槽名
子组件:接收父组件传入的参数,并将传入的参数进行处理,提取出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
})
2.2 父组件:定义数据源column、dataSource,传给子组件
2.2.1 column数据结构
const columns = [
{
title: '变化信息',
key: 'changeMsg',
slot: 'changeMsg',
},
{
title: '当前出价',
key: 'currentPrice',
slot: 'currentPrice',
},
{
title: '最低出价',
key: 'lowestPrice',
slot: 'lowestPrice',
},
{
title: '最高出价',
key: 'highestPrice',
slot: 'highestPrice',
},
]
2.2.2 dataSource数据结构
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',
},
]
2.2.3 传值给子组件
<TTable
:columns="columns"
:dataSource="dataList"
>
</TTable>
3.子组件处理数据
3.1 处理表头header
<!--header-->
<li class="ttable-item header">
<p class="ttable-item-content" v-for="item in columns" :key="item.key">{{ item.title }}</p>
</li>
3.2 处理表单内容项
<!--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>
3.3 父组件使用
<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>
4.完整代码
4.1 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>
4.2 组件的使用
<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';
4.呈现效果
样式可以根据需求进行调整
5.扩充功能
5.1 cell值修改
如上图所示,我们想要对蓝色部位进行动态修改,点击蓝色,可以编辑,失去焦点,保存内容并发送网络请求,对父组件代码进行修改
<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>
5.1.1 扩充后的效果
点击红框
修改红框的值
点击其他位置,令其失去焦点
如果觉得上述情况下,无法直接弹出键盘,也可以直接封装一个指令,在mounted时,获取焦点即可
5.2 增加loading效果
增加一个选项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 可以实现这种判断情形。
5.2.1 扩充后效果
加载数据时效果
数据加载结束后的效果
如果有帮助的话,点个赞呗~
商用转载请标明来源哦~
总结用法,希望可以帮助到你,
我是Ably,你无须超越谁,只要超越昨天的自己就好~
更多推荐
已为社区贡献11条内容
所有评论(0)