vxe-table renderer 渲染器详解,强大到没朋友的 render 渲染器使用方式

vxe-table 渲染器

  • 什么场景需要用到呢?
    1. 需要实现不同单元格编辑组件(比如:输入框、下拉框、日期选择等…)
    2. 需要定制高级筛选(比如:实现类似 Excel 筛选框或定制更加强大自定义筛选等…)
    3. 业务太多,构建可复用的渲染器
    4. 一键生成可配置化表格等

cell-render 单元格渲染

正常情况下,如果需要自定义一个单元格显示模板,通常是使用 formatter 来格式化为字符串内容,虽然基本可以满足需求;

<vxe-table
  border
  :data="tableData">
  <vxe-column type="seq" width="60"></vxe-column>
  <vxe-column field="name" title="Name"></vxe-column>
  <vxe-column field="sex" title="Sex"></vxe-column>
  <vxe-column field="time" title="Time" :formatter="formatTime"></vxe-column>
</vxe-table>
export default {
  data () {
   return {
      tableData: []
    }
  },
  created () {
    this.tableData = [
		{ name: 'Name111', sex: '1', time: 1571323971250 },
		{ name: 'Name222', sex: '0', time: 1573940857260 },
		{ name: 'Name333', sex: '1', time: 1575121185280 }
	]
  },
  methods: {
    formatTime ({ cellValue, row, column }) {
      return XEUtils.toDateString(cellValue, 'yyyy-MM-dd HH:ss:mm')
    }
  }
}

但如果需要显示自定义的 html 内容就无法满足需求了;这时候就必须通过 slot 插槽模板来渲染;

<vxe-table
  border
  :data="tableData">
  <vxe-column type="seq" width="60"></vxe-column>
  <vxe-column field="name" title="Name">
	  <template v-slot="{ row }">
	    <a class="my-link" :href="row.link">{{ row.time }}</a>
	  </template>
  </vxe-column>
  <vxe-column field="sex" title="Sex"></vxe-column>
  <vxe-column field="time" title="Time"></vxe-column>
</vxe-table>

但是通过插槽来渲染复用性太差,到处是冗余代码,这时就需要用 渲染器 + jsx 来抽象可复用的单元格渲染;

// 创建一个超链接渲染器
VXETable.renderer.add('MyLink', {
  // 默认显示模板
  renderDefault (h, cellRender, params) {
    let { row, column } = params
    return [
      <a class="my-link" href={ row.link }>{row[column.property]}</a>
    ]
  }
})
<vxe-table
  border
  :data="tableData">
  <vxe-column type="seq" width="60"></vxe-column>
  <vxe-column field="name" title="Name" :cell-render="{name: 'MyLink'}"></vxe-column>
  <vxe-column field="sex" title="Sex"></vxe-column>
  <vxe-column field="time" title="Time"></vxe-column>
</vxe-table>

这样就抽象完成!一切渲染都可以配置化;

filter-render 筛选渲染

先来看一个最简单的筛选配置

<vxe-table
  border
  :data="tableData">
  <vxe-column type="seq" width="60"></vxe-column>
  <vxe-column field="name" title="Name"></vxe-column>
  <vxe-column field="sex" title="Sex" :filters="selList"></vxe-column>
  <vxe-column field="time" title="Time"></vxe-column>
</vxe-table>
export default {
  data () {
   return {
      tableData: [],
      selList: [
      	{label: '1', value: '男'},
      	{label: '0', value: '女'}
      ]
    }
  },
  created () {
    this.tableData = [
		{ name: 'Name111', sex: '1', time: 1571323971250 },
		{ name: 'Name222', sex: '0', time: 1573940857260 },
		{ name: 'Name333', sex: '1', time: 1575121185280 }
	]
  }
}

但如果需要显示自定义的 html 内容就无法满足需求了;这时候就必须通过 slot 插槽模板来渲染;
上下文函数 context.changeOption(event, checked, option) 是在选项值发生改变是需要调用该方法,用于更新内部值

<vxe-table
  border
  :data="tableData">
  <vxe-column type="seq" width="60"></vxe-column>
  <vxe-column field="name" title="Name"></vxe-column>
  <vxe-column field="sex" title="Sex">
	  <template v-slot="{ row }">
	  	<div v-for="(option, index) in column.filters" :key="index">
	  		<input type="type" v-model="option.data" @input="context.changeOption($event, !!option.data, option)">
	  	</div>
	  </template>
  </vxe-column>
  <vxe-column field="time" title="Time"></vxe-column>
</vxe-table>

通过插槽来渲染复用性太差,到处是冗余代码,这时使用 渲染器 + jsx 来抽象可复用的筛选渲染;

// 创建一个支持输入的筛选器(仅用于简单示例,实际开发中应该封装成一个组件,不应该把复杂的渲染逻辑写在渲染器中)
VXETable.renderer.add('MyFilter', {
  // 筛选模板
  renderFilter (h, filterRender, params, context) {
    let { column } = params
    return column.filters.map(option => {
      return <input type="text" v-modal={ option.data } onInput={ evnt => { context.changeOption(evnt, !!option.data, option) } }/>
    })
  },
  // 筛选方法
  filterMethod ({ option, row, column }) {
    let cellValue = XEUtils.get(row, column.property)
    return cellValue == option.data
  }
})
<vxe-table
  border
  :data="tableData">
  <vxe-column type="seq" width="60"></vxe-column>
  <vxe-column field="name" title="Name"></vxe-column>
  <vxe-column field="sex" title="Sex" :filters="[{data: null}]" :filter-render="{name: 'MyFilter'}"></vxe-column>
  <vxe-column field="time" title="Time"></vxe-column>
</vxe-table>

edit-render 可编辑渲染

先来看一下简单可编辑表格使用

<vxe-table
  border
  :edit-config="{trigger: 'click', mode: 'cell'}"
  :data="tableData">
  <vxe-column type="seq" width="60"></vxe-column>
  <vxe-column field="name" title="Name" :edit-render="{name: 'input', attrs: { type: 'text' }}"></vxe-column>
  <vxe-column field="sex" title="Sex" :edit-render="{name: 'input', attrs: { type: 'text' }}"></vxe-column>
  <vxe-column field="time" title="Time" :edit-render="{name: 'input', attrs: { type: 'text' }}"></vxe-column>
</vxe-table>
export default {
  data () {
   return {
      tableData: []
    }
  },
  created () {
    this.tableData = [
		{ name: 'Name111', sex: '1', time: 1571323971250 },
		{ name: 'Name222', sex: '0', time: 1573940857260 },
		{ name: 'Name333', sex: '1', time: 1575121185280 }
	]
  }
}

还是老问题,如果需要显示自定义的 html 内容就无法满足需求了;这时候就必须通过 slot 插槽模板来渲染;

<vxe-table
  border
  :edit-config="{trigger: 'click', mode: 'cell'}"
  :data="tableData">
  <vxe-column type="seq" width="60"></vxe-column>
  <vxe-column field="name" title="Name" :edit-render="{name: 'input'}">
  	<template v-slot:edit="{ row }">
      <input type="text" v-model="row.name" class="custom-input">
    </template>
  </vxe-column>
  <vxe-column field="sex" title="Sex" :edit-render="{name: 'input'}">
  	<template v-slot:edit="{ row }">
      <input type="text" v-model="row.sex" class="custom-input">
    </template>
  </vxe-column>
  <vxe-column field="time" title="Time" :edit-render="{name: 'input'}">
  	<template v-slot:edit="{ row }">
      <input type="text" v-model="row.time" class="custom-input">
    </template>
  </vxe-column>
</vxe-table>

通过插槽来渲染复用性太差,再来看下 渲染器 + jsx 来抽象可复用的筛选渲染;

// 创建一个简单输入框渲染器
VXETable.renderer.add('MyInput', {
  // 可编辑激活模板
  renderEdit (h, editRender, { row, column }) {
    return [
      <input class="my-cell" text="text" v-modal={ row[column.property] }/>
    ]
  },
  // 可编辑显示模板
  renderCell (h, editRender, { row, column }) {
    return [
      <span>{ row[column.property] }</span>
    ]
  }
})
<vxe-table
  border
  :data="tableData">
  <vxe-column type="seq" width="60"></vxe-column>
  <vxe-column field="name" title="Name" :edit-render="{name: 'MyInput'}"></vxe-column>
  <vxe-column field="sex" title="Sex" :edit-render="{name: 'MyInput'}"></vxe-column>
  <vxe-column field="time" title="Time" :edit-render="{name: 'MyInput'}"></vxe-column>
</vxe-table>

到此结束,由于渲染器的参数及高级用法就比较复杂了,这里仅仅只是介绍了简单的用法,更多进阶用于可以看官方文档哈!

Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐