1. Required environment and dependencies
- view 3
- gonePlus
2. A chestnut
- Introduce a basic table component
<template>
<el-table :data="tableData" style="width: 100%">
<el-table-column type="selection" width="50" /> // 添加勾选框
<el-table-column type="index" width="80" align="center" label="序号" /> // 添加序号
<el-table-column v-for="item in tableHeader" :prop="item.prop" :label="item.label" :width="item.width" :key="item.prop">
// 对其中某一列特殊处理(当prop等于tag的时候,把这列数据用tag标签包裹)
<template #default="scope">
<el-tag v-if="item.prop == 'tag'" :type="scope.row.tag === 'Home' ? 'warning' : 'success'">{
{
scope.row.tag }}</el-tag>
</template >
</el-table-column>
// 单独设置操作列
<el-table-column fixed="right" label="操作" width="150">
<template #default="scope">
<el-button link type="primary" size="small" @click="clickDelete(scope.$index, tableData)">删除</el-button>
<el-button link type="primary" size="small" @click="clickEdit(scope)">编辑</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script>
import {
tableHeader, tableData } from './content/contentTableData' // 路径以自己存放的位置为准
</script>
- Create a new ts file to store the data of the table header and table content
import {
reactive } from 'vue'
import nameTag from '../cmpts/nameTag.vue'
// 表头数据
const tableHeader = reactive([
{
prop: 'date',
label: '时间',
width: 120
},
{
prop: 'name',
label: '姓名',
width: 120,
},
{
prop: 'age',
label: '年龄',
width: 120,
},
{
prop: 'state',
label: '国家',
width: 120
},
{
prop: 'city',
label: '城市',
width: 120
},
{
prop: 'address',
label: '地点',
width: 250
},
{
prop: 'tag',
label: '标记',
width: 120
}
])
// 表格数据
const tableData = reactive([
{
date: '2016-05-03',
name: 'Tom',
age: 18,
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
tag: 'Home'
},
{
date: '2016-05-02',
name: 'Tom',
age: 8,
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
tag: 'Office'
},
{
date: '2016-05-04',
name: 'Tom',
age: 20,
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
tag: 'Home'
},
{
date: '2016-05-01',
name: 'Tom',
age: 28,
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
tag: 'Office'
}
])
export {
tableHeader, tableData }
- Encapsulate a renderTable component, and cooperate with the customRender function to process any column of the table
<template>
<renderTable />
</template>
<script setup lang="ts">
const props = defineProps({
render: {
type: Function,
require: true
},
row: {
type: Object,
require: true
},
column: {
type: Object,
require: true
}
})
const renderTable = {
render: () => {
const {
row, column, render: customRender } = props
const params = {
row, column }
const vnode = customRender!(params)
return vnode
}
}
</script>
<style lang="less" scoped></style>
- Add the customRender function to the configuration file of the tabular data to re-render the current column
// 1. 对年龄列:用一个span标签渲染,当年龄大于等于18的时候显示#267EE5颜色,否则显示#FF3543颜色。
// 2. 对姓名列:重新定义了一个nameTag组件,并引入
import {
reactive, h } from 'vue'
const tableHeader = reactive([
{
prop: 'age',
label: '年龄',
width: 120,
customRender: ({
row }) => {
return h('span', {
style: {
color: row.age >= 18 ? '#267EE5' : '#FF3543' } }, row.age)
}
},
{
prop: 'name',
label: '姓名',
width: 120,
customRender: ({
row }: any) => {
return h(nameTag, {
row })
}
},
])
// 说明:h函数用于创建一个vnode,在vue中是createVNode 函数的简写,接收三个参数
// 参数1. 标签名或组件 参数2. 标签的属性或事件 参数3. 内容
- Add judgment to the table component, if the customRender attribute is configured, render according to this
<template #default="scope">
<renderTable
v-if="item.customRender && typeof item.customRender === 'function'"
:render="item.customRender"
:row="scope.row"
:column="scope.column"
/>
</template>
- Chestnut's complete code
table component:
<template>
<el-table :data="tableData" style="width: 100%">
<!-- 表格部分 -->
<el-table-column type="selection" width="50" />
<el-table-column type="index" width="80" align="center" label="序号" />
<el-table-column v-for="item in tableHeader" :prop="item.prop" :label="item.label" :width="item.width" :key="item.prop">
<template #default="scope">
<el-tag v-if="item.prop == 'tag'" :type="scope.row.tag === 'Home' ? 'warning' : 'success'">{
{
scope.row.tag }}</el-tag>
<renderTable
v-if="item.customRender && typeof item.customRender === 'function'"
:render="item.customRender"
:row="scope.row"
:column="scope.column"
/>
</template>
</el-table-column>
<!-- 表格操作部分 -->
<el-table-column fixed="right" label="操作" width="150">
<template #default="scope">
<el-button link type="primary" size="small" @click="clickDelete(scope.$index, tableData)">删除</el-button>
<el-button link type="primary" size="small" @click="clickEdit(scope)">编辑</el-button>
</template>
</el-table-column>
<!-- 表格操作部分 -->
</el-table>
<!-- 表格部分 -->
<el-tree></el-tree>
</template>
<script setup lang="ts">
import {
tableHeader, tableData } from './content/contentTableData'
import renderTable from './cmpts/renderTable.vue'
// 删除逻辑
const clickDelete = (index: number, data: any) => {
data.splice(index, 1)
}
// 编辑逻辑
const clickEdit = (value: any) => {
console.log(value)
}
// 表格数据按照时间排序,最新的时间在最上面(从大到小)
const timeOrder = () => {
tableData.sort(function (a: {
date: string }, b: {
date: string }) {
return a.date < b.date ? 1 : -1 // 从大到小
})
}
timeOrder()
</script>
<style lang="less" scoped></style>
nameTag component:
<template>
<el-tag>{
{
row.name }}</el-tag>
</template>
<script setup lang="ts">
const props = defineProps({
row: {
type: Object,
required: true
}
})
console.log(props)
</script>
<style lang="less" scoped></style>
renderTable component:
vue2 writing method:
<script lang="ts">
export default {
props: {
render: {
type: Function,
require: true
},
row: {
type: Object,
require: true
},
column: {
type: Object,
require: true
}
},
render() {
const {
row, column, render: customRender } = this
const params = {
row, column }
const vnode = customRender!(params)
return vnode
}
}
</script>
<style lang="less" scoped></style>
Vue3 writing method:
<template>
<renderTable />
</template>
<script setup lang="ts">
const props = defineProps({
render: {
type: Function,
require: true
},
row: {
type: Object,
require: true
},
column: {
type: Object,
require: true
}
})
const renderTable = {
render: () => {
const {
row, column, render: customRender } = props
const params = {
row, column }
const vnode = customRender!(params)
return vnode
}
}
</script>
<style lang="less" scoped></style>
contentTableData.ts file:
import {
reactive, h } from 'vue'
import nameTag from '../cmpts/nameTag.vue'
// 表头数据
const tableHeader = reactive([
{
prop: 'date',
label: '时间',
width: 120
},
{
prop: 'name',
label: '姓名',
width: 120,
customRender: ({
row }: any) => {
return h(nameTag, {
row })
}
},
{
prop: 'age',
label: '年龄',
width: 120,
customRender: ({
row }) => {
return h('span', {
style: {
color: row.age >= 18 ? '#267EE5' : '#FF3543' } }, row.age)
}
},
{
prop: 'state',
label: '国家',
width: 120
},
{
prop: 'city',
label: '城市',
width: 120
},
{
prop: 'address',
label: '地点',
width: 250
},
{
prop: 'tag',
label: '标记',
width: 120
}
])
// 表格数据
const tableData = reactive([
{
date: '2016-05-03',
name: 'Tom',
age: 18,
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
tag: 'Home'
},
{
date: '2016-05-02',
name: 'James',
age: 8,
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
tag: 'Office'
},
{
date: '2016-05-04',
name: 'Tom',
age: 20,
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
tag: 'Home'
},
{
date: '2016-05-01',
name: 'Tom',
age: 28,
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
tag: 'Office'
}
])
export {
tableHeader, tableData }
- result
未完待续...