vue2/vue3基于element-table实现render函数
vue2实现render
// 只展示核心代码
// standarTable.vue
<el-table
:data="dataSource"
ref="standarTable"
>
<template v-for="(col, key) in columns || []">
<!-- 操作列/自定义列 -->
<slot v-if="col.slot" :name="col.prop || col.slot"></slot>
<el-table-column v-else>
<template slot-scope="scope">
<!-- 正常渲染 -->
<template v-if="!col.render">
<template v-if="col.formatter">
<span v-html="col.formatter(scope.row, col)"></span>
</template>
<template v-else>
<span>{{scope.row[col.prop]}}</span>
</template>
</template>
<!-- render函数 -->
<template v-else>
{{ renderToHtml(col, scope.row) }}
<slot :name="col.prop"></slot>
</template>
</template>
</el-table-column>
</template>
<template slot="empty">
<avue-empty desc="暂无数据" />
</template>
</el-table>
<script>
export default {
name: "standarTable",
methods: {
// 使用js动态新增一个slot实现render函数jsx语法渲染
renderToHtml(col, row) {
if (typeof col.render === 'function') {
this.$slots[col.prop] = [col.render(row)]
return
}
return
},
}
}
</script>
// 调用
<template>
<standar-table :columns="columns"></standar-table>
</template>
<script>
export default {
data() {
return {
columns: [
{
label: "测试",
prop: "upperLimit",
align:'center',
render:(row) => {
return <span>{row.upperLimit}</span>
}
}
]
}
}
}
</script>
vue3实现render
由于vue3试了很多方法都没法实现js动态添加slot,就换了种实现方式。
// 先安装支持jsx语法的依赖,方便render函数里使用html标签
npm install @vitejs/plugin-vue-jsx --save-dev
// 在vite.config.js配置文件里添加插件配置
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vueJsx from '@vitejs/plugin-vue-jsx'
export default ({ mode }) => defineConfig({
plugins: [
vue(),
// 支持jsx语法
vueJsx(),
]
})
// 只展示核心代码
// standarTable.vue
<el-table
:data="tableData"
v-loading="loading"
>
<el-table-column label="序列号" v-if="showIndex" width="70" align="center">
<template #default="scope">
<span>{{ (pageObj.page - 1) * pageObj.size + scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column
v-for="(column, index) in columns"
>
<template #default="scope">
<!-- 正常渲染 -->
<template v-if="!column.render">
<div v-if="column.slot">
<slot
:item="tableData[scope.$index]"
:index="scope.$index"
:name="column.slot"
></slot>
</div>
<span v-else>{{ scope.row[column.prop] }}</span>
</template>
<!-- render函数 -->
<!-- 如果rander函数里需要套上html标签,父组件《script lang="jsx》需要加上lang="jsx" -->
<template v-else>
<expandDom :column="column" :row="scope.row" :render="column.render" :index="scope.$index"></expandDom>
</template>
</template>
</el-table-column>
</el-table>
<script>
// 引入利用render渲染的组件,后缀名定的是什么类型的文件要将后缀名写全
import expandDom from './commonJs/expandDom.jsx'
export default {
name: "standarTable",
components:{expandDom},
props: {...}
}
</script>
// expandDom.jsx
// 不使用template模板渲染,使用render方式渲染,解析传进来的函数
import { defineComponent } from 'vue';
export default defineComponent({
name: 'expandDom',
props: {
row: Object,
render: Function,
index: Number,
column: {
type: Object,
default: null
}
},
render() {
// 这里能使用react的空标签<>就是@vitejs/plugin-vue-jsx插件的功劳
// return this.render(this.row)
return <>{this.render(this.row)}</>
}
})
// 调用
<template>
<standarTable
:columns="columns"
ref="standarTable"
>
</standarTable>
</template>
// 加上lang="jsx"才能支持jsx语法
<script lang="jsx">
export default {
components:{...},
setup(props) {
const columns = [
{ prop: "title", name: "标题", width: 150,render:(row) => {
// return row.title
return <span>{row.title}</span>
}}
}]
}
</script>