背景
由于表格数据比较同构,有时候列配置是动态的,此时希望使用v-for来配置column
<template><el-table :data="tableData"> <el-table-column v-for="col in columns" :key="col.dataIndex" :label="col.title" :prop="col.dataIndex" :formatter="col.render" /></el-table></template><script>const PHONE_COLS = [ { title: '录音id', dataIndex: 'attach_id' }, { title: '接听客服', dataIndex: 'handle_user_info' }, { title: '呼叫类型', dataIndex: 'type_desc' }, { title: '通话时长', dataIndex: 'duration' },];const WORK_COLS = [ { title: '工单id', dataIndex: 'attach_id' }, { title: '创建客服', dataIndex: 'handle_user_info' }, { title: '创建时间', dataIndex: 'c_t' }, { title: '工单来源', dataIndex: 'source' }, { title: '工单分类', dataIndex: 'ws_type', render: (row, column, cell) => (cell || []).join(',') }];export default { data () { return { columns: PHONE_COLS, tableData: [], tableTotal: 0, } },}</script>
可以看到代码比直接使用template更加简洁,另外也可以利用formatter
函数处理简单的自定义字符串
问题:自定义template
的列
当我们希望使用配置的方式来达到<template v-slot>
的效果,需要借助于vue
的render
函数与jsx
模板
jsx
引入方法详见渲染函数 & JSX
此时所有想创建vnode的时候都可以借助jsx
来实现,jsx
编译需要一个createElement
方法,如下
// h就是createElementfunction render(h) { var a = 'test' return ( <el-tooltip class="item" effect="dark"> {a} </el-tooltip> )}
table的formatter
方法也支持返回vnode渲染,因此我们可以想办法拿到createElement
后使用jsx来达到复杂列的渲染,如下
<template><el-table :data="tableData"> <el-table-column v-for="col in columns" :key="col.dataIndex" :label="col.title" :prop="col.dataIndex" :formatter="col.render" /></el-table></template><script>let createElementconst WORK_COLS = [ { title: '工单id', dataIndex: 'attach_id' }, { title: '创建客服', dataIndex: 'handle_user_info' }, { title: '创建时间', dataIndex: 'c_t' }, { title: '工单来源', dataIndex: 'source' }, { title: '工单分类', dataIndex: 'ws_type', render: (row, column, cell) => (cell || []).join(',') }, { title: '工单描述', dataIndex: 'desc', render: (row, column, cell) => { return (function(h) { return ( <div domPropsInnerHTML={cell}></div> ); })(createElement) } },];export default { data () { return { columns: WORK_COLS, tableData: [], tableTotal: 0, } }, mounted() { createElement = this.$createElement }}</script>
说明
- 为了使用
jsx
模板,我们制造了带有h函数的匿名函数来生成vnode
Note the h function, which is a shorthand for a Vue instance's $createElement method, must be in the scope where the JSX is. 详细
- 获取
createElement
方法比较多,比如可以把columns
放在组件内部通过this.$createElement
,此处是1个简单例子 - 我们这里的例子返回的是带html特殊符号的字符串,需要使用innerHTML才能正确渲染,这里react的
dangerouslySetInnerHTML
无效,需要使用babel-plugin-transform-vue-jsx
的属性domPropsInnerHTML
以上。