对于 vxe-table 的介绍这里就不说了,常规用法也不多累赘,应该按文档撸就可以了。这里主要讲下关于自定义渲染的一些方式
1、先看看部分自定义的效果
熟悉 Element 的朋友可能已经发现了,这个表格里面用了相关组件,比如:
tooltip — 实现了hover气泡
el-link — 渲染了表格内容
el-dropdown — 实现下拉菜单
最后还有一个空数据的渲染 el-empty,同时细心的朋友可能也发现了,排序那里也是自定义的图标。
小总结:
我们知道了,表头的内容、单元格的内容、部分图标都可以自定义实现,进而完成我们的需求。
2、如何实现上述需求?
通过查阅文档,我们发现要是实现自定义渲染有两种方式:
1、插槽 就跟 vue 中插槽一个意思
2、渲染器 好比是注册了一个 vxe-table 的组件
插槽的方式这里不讲,应该来说都能理解到,主要示范下 渲染器 的方式 。(我推荐先大致浏览下 文档,我个人比较倾向于看 API 那栏,就可以看到自己使用的组件有哪些props和其他需要的)
3、先搞定一个简单的吧 — 实现一个空内容渲染器
声明:本人采用的 vxe-grid 组件
老规矩,看文档
可以看到,可以通过 empty-text 直接传递,也可以通过渲染器,那我们肯定是通过渲染器来搞撒(vxe 属性中带-render的通常是渲染器)
渲染器文档
那么,先照抄
// 这样就算注册了一个渲染器 name 为 NotData
VXETable.renderer.add('NotData', {// 空内容模板 这个函数是 vxe 固定的,渲染表格头部为 renderHeader,其他科看文档renderEmpty () {// 渲染器接收的返回值类型为 []vnode 因此,这样返回return [<el-empty description="暂时没有数据"></el-empty>]}
})// 使用 直接通过 props 传入
data() {return {gridOptions: {...emptyRender: {name: 'NotData'}}}
}
可以发现,其实这就跟注册组件一样,有人可能问,那我怎么传递参数或者绑定时间呢?下面以渲染一个单元格为例
4、渲染单元格
还是老规矩,先看文档
上面渲染空内容我们大概知道渲染器大致格式,xxx.add(name,option),要求我们提供一个 name ,这个name就是 prop 中渲染器参数的name选项,同时 option 选项中内置了渲染函数(也就是上图的配置参数)
对于渲染器,vxe 其实已经给你定好了,比如你想渲染空内容,就得用 empty-render ,想渲染单元格的内容,就得用cell-render…对于这个建议好好理解下,不然估计会乱用
总的来说,就是你得先知道你想自定义渲染的地方是属于哪一种渲染器,然后再去看对应文档。比如现在我们是想渲染单元格,那么就得看 cell-render,每个 render 其实提供的函数也不太一样,所以最好是仔细看
// 简单再解释下 以cell-render为例
renderHeader ---- 你想自定义渲染那一列的表头内容
renderDefault --- 你想自定义渲染那一列单元格的内容,就好比我们现在想渲染操作那一列(更多操作),就得用这个去渲染单元格
...这些渲染函数都提供了三个参数
renderHeader (h, renderOpts, params: { column, columnIndex, columnIndex, $rowIndex, $table }) h --- 应该类似vue render 函数的 h(具体我们看)renderOpts --- 渲染的时候传递的参数(你想传递的数据、事件等,都通过这个参数去获取)params --- 从文档应该可以看出,大致就是些当前列的一些信息
换句话说,当我们通过自定义的方式去渲染了一个单元格,那我怎么给这个单元格传递参数?绑定事件?事件响应时如何获取当前列的信息呢?答案就是通过这些render函数提供的参数来获取
5、来渲染下表格中操作那列
渲染器的编写:
VXETable.renderer.add('Operation', {// Default --- 默认的表格单元格内容renderDefault(_, renderOpts, params) {// 直接从 renderOpts 解构出我们传递的事件、参数、包括ele组件的一些自定义事件const { events,props: { option,command } } = renderOptsreturn [<div><span class="editor-box pointer" onClick={ ()=> events(params) } >编辑</span><span style="margin: 0 10px" > | </span><el-dropdown placement="bottom" oncommand={ (val) => { command(val,params.row) } } ><span class="el-dropdown-link pointer" >更多</span><el-dropdown-menu slot="dropdown">{option.map((item) => {return (<el-dropdown-item command={item.id} >{item.text}</el-dropdown-item>)})}</el-dropdown-menu></el-dropdown></div>]}
})
在 props 中 columns 属性里定义我们的渲染器
// data
columns = [ { field: 'operation', title: '操作', showOverflow: true ,fixed: 'right',width: 200,cellRender: {name: 'Operation',events: (e) => { this.onTabMoreEditor(e) },props: {option: [{id: 'a',text: '删除'},{id: 'b',text: '狮子头'},{id: 'c',text: '螺蛳粉'}],command: this.onTabCommand}}}]methods: {/** 更多-编辑 **/onTabMoreEditor({ row: { name } }) {console.log(name)},/** 更多 **/ onTabCommand(val,row) {switch (val) {case 'a':console.log('当前选择 删除')this.gridOptions1.data = this.gridOptions1.data.filter((item) => item.id != row.id)break;case 'b':console.log('当前选择 狮子头')break;case 'c':console.log('当前选择 螺蛳粉')break;default:break;}}}
如上所示,我们编写好了渲染器,需要传递的事件和绑定的参数都可以通过渲染器提供的 props和events选项传递到渲染器组件中,进而完成业务功能
6、vxe-table mixin 的用法
当我们需要写多个渲染器时,又懒得通过 VXETable.renderer.add 方式去挨个添加,于是有了 mixin 的用法,就跟vue全局注册组件一样
const renderMap = {// 这种方式应该不用多说吧MyLink: {renderDefault (h, renderOpts, params) {let { row, column } = paramslet { events } = renderOptsreturn [<el-link type="primary" onClick={ () => events(params) } >{row[column.property]}</el-link>]}}
}
// mixin 接收一个 map 结构
VXETable.renderer.mixin(renderMap)
7、个人小总结
渲染器
- 用来自定义渲染表格内容,使用 renderer.add(name,option = {}) option 可以理解为像 vue 的组件选项
- 通常有几个渲染的api
- renderDefault — 单元格的显示内容
- renderHeader — 表格表头的渲染器
- …
- 这些渲染的 api 大部分都是三个参数
- h – 渲染函数(一般用不到)
- renderOpts – 像cellRender时传递的prop、event等参数
- params – 表格当前行、列数据等(xxindex等)
- tips
- 1、在编写时,应先考虑是属于哪种渲染器,单元格?内容?空数据?等
- 2、渲染器函数返回值都是 []vnode 类型
- 3、如果编写的渲染器不显示(甚至不执行且编写无误)时,考虑是否和 vxe 默认配置重叠了
- 笔者在编写 SeqIcon 时就遇到了,始终渲染的是默认的序号,原因就是 columns 配置项中,我又写了 type=seq 因此就渲染了默认的序号
- 渲染器和插槽区别
- 其实两者自由度都高,相对来说渲染器更加符合组件的思想,性能要好些