解决问题
只举一个例子(我正好需要用到的)
在写中后台时, 如果对 表格组件 再度封装了, 比如这样的
以element-ui 为例:
<template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" label="日期" width="180"> </el-table-column> <el-table-column prop="name" label="姓名" width="180"> </el-table-column> <el-table-column prop="address" label="地址"> </el-table-column> </el-table> </template>
对html数据化, 封装成一个组件.
// complex-table.vue <template> <el-table :data="list" style="width: 100%;" > <el-table-column v-for="col in columns" :key="col.prop" v-bind="col"></el-table-column> </el-table> </template> <script> export default { props: { columns: Array } } </script> -------------------------- // index.vue <template> <div class="box_container"> <complex-table :columns="tableColumns" /> </div> </template> <script> export default { data() { return { tableColumns: [ { label: '日期', prop: 'sn', align: 'center' }, { label: '姓名', prop: 'phone', align: 'center' }, { label: '地址', prop: 'address', align: 'center' } ] } } } </script>
那么问题来了, 如果我要在table中加入头像列, 但是后端返回的是url地址, 你又怎么办呢,你可以这样
// complex-table.vue ... <el-table> <el-table-column v-for="col in columns" :key="col.prop" v-bind="col"> <template slot-scope="scope"> <template v-if="col.prop==='avatar'"> <el-avatar :src="row.avatar" /> </template> <template v-else> <span>{{ scope.row[col.prop] }}</span> </template> </template> </el-table-column> </el-table> ... // index.vue ... data() { return { tableColumns: [ { label: '头像', prop: 'avatar', align: 'center' }, { label: '日期', prop: 'date', align: 'center' }, { label: '姓名', prop: 'name', align: 'center' }, { label: '地址', prop: 'address', align: 'center' } ] } } ...
万一又是 <el-tag>
标签, el-button
不能一直v-if吧
或许也可以使用 <component :is="**" v-bind="**" >
这种形式, 如果遇到方法传值又感觉差点什么,差scope传值了
解决方案
使用函数式组件, 可灵活使用, 原理跟 valueFormat 类似, 不废话直接上代码
新建文件 columnRender.js
/* * @Description: 函数式组件渲染单元表格 * @Author: 仲灏<izhaong 164165005@qq.com> * @Date: 2020-09-16 15:33:25 * @LastEditors: 仲灏<izhaong 164165005@qq.com> * @LastEditTime: 2020-09-16 15:47:23 */ export default { functional: true, props: { row: Object, render: Function }, render(h, ctx) { const params = { row: ctx.props.row } return ctx.props.render(h, params) } }
// complexTable ... <template v-else-if="'render' in col"> <!-- <component :is="col.tag" v-bind="col.attrs">{{ col.tagValue }}</component> --> <Render :row="row" :render="col.render" /> </template> ... // index.js tableColumns: [ { label: 'name', prop: 'name', align: 'center' }, { label: '是否有效', prop: 'isValid', align: 'center', render: (h, { row }) => { return h('el-tag', { attrs: { type: row.isValid ? 'success' : 'info' }}, row.isValid ? '有效' : '无效') } } ]
结语
第一次bb这个多话, 之前直接就啪~ 贴代码了.
当然如果封装的组件足够强大, 能够兼顾涵盖该项目大部分业务, 就可以把组件当做页面使用, 全部使用纯数据驱动, 当然你的业务相似度要高