对于 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 } } = renderOpts
        return [
            <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 } = params
            let { events } = renderOpts
            return [
                <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 因此就渲染了默认的序号
  • 渲染器和插槽区别
  • 其实两者自由度都高,相对来说渲染器更加符合组件的思想,性能要好些
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐