本文章,没有原理,没有乱七八糟的废话,除了这一行以外,其余直接上代码,如有不妥,感谢留言指正
为什么用render函数写JSX组件?
- 拓展性更好
- 更解耦
- 性能好
- 抛弃插槽的弊端
对比
<el-table
ref="table"
class="table"
:data="table.data"
v-bind="table.config"
v-on="table.on">
<el-table-column
v-for="(item, index) of table.columns.filter(key => !key.isButton)"
:key="index"
v-bind="item">
<!--如果我们想在这里加上自定义的元素,那么我们只能用插槽,或者改写column组件-->
<!--插槽的话,我们得用<component></component>标签,写这个,我们得多传很多参数,导致参数结构混乱-->
</el-table-column>
<el-table-column
v-for="(item, i) of table.columns.filter(key => key.isButton)"
:key="i + Math.random()"
v-bind="item">
<template slot-scope="scope">
<el-button
v-for="i of item.btns"
:key="i.code"
@click="handlerClick({i, scope})"
v-bind="i">
{{ i.name }}
</el-button>
</template>
</el-table-column>
</el-table>
export default {
name: 'table',
props: {
table: {
type: Object,
default () {
return {}
}
}
},
methods: {
handlerClick (data) {
this.$emit('handlerClick', data)
}
}
}
于是我们改成render函数JSX组件
export default {
name: 'render-table',
props: {
table: {
type: Object,
default: () => {
return {}
}
}
},
methods: {
handlerClick (e, i, props) {
// 内部先解决冒泡问题
e.stopPropagation()
// 然后根据是否带on函数,来进行回调
if (i.on) {
i.on(props, i.code)
}
}
},
render () {
return (
<div class="plus-render-table">
<el-table { ...{ on: { ...this.table.on } } } { ...{ attrs: this.table.config } } ref="plus-render-table" class="table" data={ this.table.data }>
{
this.table.columns.filter(key => !key.isButton).map(item => {
if (item.renderCell) {
const scoped = (item) => {
return {
default: props => {
return (item.renderCell(props, item))
}
}
}
const scopedSlots = scoped(item)
return <el-table-column { ...{ attrs: item } } { ...{ scopedSlots } }></el-table-column>
}
return <el-table-column { ...{ attrs: item } }></el-table-column>
})
}
{
this.table.columns.filter(key => key.isButton).map(item => {
const scopedSlots = {
default: (props) => {
return item.btns.map(it => {
return <el-button on-click={ (e) => this.handlerClick(e, it, props) } { ...{ attrs: it } }>{ it.name }</el-button>
})
}
}
return <el-table-column { ...{ attrs: item } } { ...{ scopedSlots } }></el-table-column>
})
}
</el-table>
</div>
)
}
}
这样,我们的table组件,就改写完成了
来看看怎么用它
table: {
// table的列配置
columns: [
{ type: 'selection' },
{ type: 'index', label: '序号', align: 'center' },
{
prop: 'name',
// 这是render函数来渲染表头的方式
renderHeader: (h, scope) => {
return <div>名称</div>
},
renderCell: (props) => {
return <div class="common-row-start align-center">{props.row[props.column.property]}</div>
}
},
{
label: '年龄',
prop: 'age',
sortable: true,
formatter: (row, column, cellValue, index) => {
return row.age
}
},
{
label: '性质',
prop: 'address',
// 这个是一个render函数,通过render函数就可以写我们的特殊配置,只能有一个根元素,也就是return括号里面的第一个标签必须是唯一的div,它没有兄弟元素
renderHeader () {
return (
<div>
<span>岗位性质</span>
<el-tooltip effect="light" placement="right">
<div slot="content">
<div style="text-align: center;margin-bottom: 5px">说明</div>
<div>
<div>xxxxxxxxxxxxxx</div>
<div>aaaaaaaaaaaaaaaa</div>
<div>qqqqqqqqqqqqqqqqqq</div>
</div>
</div>
<i class="el-icon-question" style="font-size: 16px;margin-left: 3px;vertical-align: -10%;"></i>
</el-tooltip>
</div>
)
},
showOverflowTooltip: true
},
{
label: '操作',
isButton: true,
width: 150,
btns: [
{
name: '查看详情',
code: 'info',
type: 'text',
size: 'mini',
on: (props, code) => {
console.log(props, code)
}
},
{
name: '新增',
code: 'add',
type: 'text',
size: 'mini',
on: (props, code) => {
console.log(props, code)
}
},
{
name: '修改',
code: 'edit',
type: 'text',
size: 'mini',
on: (props, code) => {
console.log(props, code)
}
},
{
name: '删除',
code: 'remove',
type: 'text',
size: 'mini',
on: (props, code) => {
console.log(props, code)
}
},
{
name: '启用',
code: 'enable',
type: 'text',
size: 'mini',
on: (props, code) => {
console.log(props, code)
}
},
{
name: '停用',
code: 'disable',
type: 'text',
size: 'mini',
on: (props, code) => {
console.log(props, code)
}
}
]
}
],
config: {
stripe: true,
border: true,
height: 300,
maxHeight: 600,
size: 'mini',
fit: true,
showHeader: true,
highlightCurrentRow: true,
showSummary: false,
emptyText: '没有数据'
},
data: _this.data
}