前言
新项目 Elemnet UI 组件业务封装,封装需求满足后期不修改业务代码,直接更新前端的封装组件的UI库代码即可实现无缝切换UI库的需求。目前新项目的功能产品还在梳理,项目第一期还未开始,前端技术小组先行进行的组件封装。
Table 组件封装目标
- 封装的用法要和 Element UI Table 组件的用法保持一致
- 目的是降低引用(使用)成本
- 支持纯数据绑定
- 支持自定义模板满足业务定制化需求
Table 组件封装内容
目录结构
components 封装组件目录
talbe
Index.vue
TableColumn.vue
Views
CenterPage.vue 组件调用层
table/Index.vue
这个文件默认封装了 el-table
组件外层,里面使用 v-bind="$attrs"
和 :xxx="config.xxx"
模式,在 el-table
内层使用 slot
来接受,这样可以满足表格的自定义模板需求,如果只是渲染基本数据,可以直接把 el-table-column
也封装好,如代码中的注释部分
<template>
<div>
<!-- v-model="config.value" -->
<el-table
v-bind="$attrs"
:height="config.height"
:max-height="config.maxHeight"
:stripe="config.stripe"
:border="config.border"
:size="config.size"
:fit="config.fit"
:show-header="config.showHeader"
:highlight-current-row="config.highlightCurrentRow"
:row-class-name="config.rowClassName"
:row-style="config.rowStyle"
:cell-class-name="config.cellClassName"
:cell-style="config.cellStyle"
:header-row-class-name="config.headerRowClassName"
:header-row-style="config.headerRowStyle"
:header-cell-class-name="config.headerCellClassName"
:header-cell-style="config.headerCellStyle"
:row-key="config.rowKey"
:empty-text="config.emptyText"
:default-expand-all="config.defaultExpandAll"
:expand-row-keys="config.expandRowKeys"
:default-sort="config.defaultSort"
:tooltip-effect="config.tooltipEffect"
:show-summary="config.showSummary"
:sum-text="config.sumText"
:summary-method="config.summaryMethod"
:span-method="config.spanMethod"
:select-on-indeterminate="config.selectOnIndeterminate"
:indent="config.indent"
:lazy="config.lazy"
:load="config.load"
:tree-props="config.treeProps"
v-on="$listeners"
>
<slot></slot>
<!-- <template v-for="(v, i) in config.columns" >
<el-table-column v-if="!v.slot" :key="i" :prop="v.prop" :label="v.label" :width="v.width">
</el-table-column>
<el-table-column v-else :key="i" :prop="v.prop" :label="v.label" :width="v.width">
<slot></slot>
</el-table-column>
</template> -->
</el-table>
</div>
</template>
<script>
export default {
name: 'Table',
props: {
content: {
type: String,
default: ''
},
config: {
type: Object,
default: () => { }
}
}
}
</script>
table/TableColumn.vue
这个文件封装的 el-table-column
, 这里面同样了用了 slot
主要用于支持表格列中的自定义部分,添加了一个自定义的参数 isNativeRenter
,表示当前列配置是否是原生数据绑定渲染
<template>
<!-- v-model="config.value" -->
<el-table-column
v-bind="$attrs"
:type="config.type"
:index="config.index"
:column-key="config.columnKey"
:label="config.label"
:prop="config.prop"
:width="config.width"
:min-width="config.minWidth"
:fixed="config.fixed"
:render-header="config.renderHeader"
:sortable="config.sortable"
:sort-method="config.sortMethod"
:sort-by="config.sortBy"
:sort-orders="config.sortOrders"
:resizable="config.resizeable"
:formatter="config.formatter"
:show-overflow-tooltip="config.showOverflowTooltip"
:align="config.align"
:header-align="config.headerAlign"
:class-name="config.className"
:label-class-name="config.labelClassName"
:selectable="config.selectable"
:reserve-selection="config.reserveSelection"
:filters="config.filters"
:filter-placement="config.filterPlacement"
:filter-multiple="config.filterMultiple"
:filter-method="config.filterMethod"
:filtered-value="config.filteredValue"
v-on="$listeners"
>
<template slot-scope="{ row, column, $index }">
<slot :nativeData="[row, column, $index]" name="custom"></slot>
<span v-if="!config.isNativeRenter">{{ row[column.property] }}</span>
</template>
<template slot="header">
<slot name="header"></slot>
</template>
</el-table-column>
</template>
<script>
export default {
name: 'TableColumn',
props: {
content: {
type: String,
default: ''
},
config: {
type: Object,
default: () => { }
}
}
}
</script>
注意
这里面的 <template><el-table-column>
的层级结构中间不能有任何其他元素,否则会影响表格列数据的正常排序。如下代码就不可取
<template>
<div>
<el-table-column></el-table-column>
</div>
</template>
CenterPage.vue
基础表格调用,只渲染数据
template
<table :config="table.config" :data="table.data">
<table-column :config="table.config.columns[0]"></table-column>
<table-column :config="table.config.columns[1]"></table-column>
<table-column :config="table.config.columns[2]"></table-column>
</table>
script
table: {
config: {
columns: [
{
prop: 'date',
label: '日期'
},
{
prop: 'name',
label: '姓名'
},
{
prop: 'address',
label: '地址'
width: 300
}
]
},
data: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
}]
},
自定义列模板表格
<c-table :config="table3.config" :data="table2.data">
<table-column :config="table3.config.columns[0]">
<template slot="custom" slot-scope="{ nativeData }">
<span style="margin-left: 10px">{{ nativeData[2] }}</span>
</template>
</table-column>
<table-column :config="table3.config.columns[1]">
<template slot="custom" slot-scope="{ nativeData }">
<i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ nativeData[0].date }}</span>
</template>
</table-column>
<table-column :config="table3.config.columns[2]"></table-column>
<table-column :config="table3.config.columns[3]"> </table-column>
<table-column :config="table3.config.columns[4]">
<template slot="custom" slot-scope="{ nativeData }">
<el-button
@click="handleSelectClick(nativeData)"
type="primary"
size="small"
>查看</el-button
>
<el-button type="danger" size="small">删除</el-button>
</template>
</table-column>
</c-table>
数据层
table3: {
config: {
columns: [
{
width: '50',
type: 'index'
},
{
prop: 'date',
label: '日期',
width: '200',
key: 'date',
sortable: true,
isNativeRenter: true
},
{
prop: 'name',
label: '姓名',
key: 'name',
sortable: true
},
{
prop: 'address',
label: '地址',
width: '400',
key: 'address'
},
{
label: '操作',
width: '200',
fixed: 'right',
}
],
border: true,
stripe: true,
size: 'mini'
},
data: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
}]
}
封装过程中遇到的问题和思考
-
整个封装过程使用到的技术点相关内容,主要为
slot 的合理使用
、父子组件的互相传值
、父子组件的事件触发
-
组件封装的内容在我们目前项目的高业务复杂度(包含高度自定义设计出来的功能,以及UI层的特殊需求效果)的项目中,当前业务未开展的情况下,无产品原型,无UI设计规范及效果,纯技术层封装对于业务的支持目前不确定,部分组件在开发过程使用可能需要二次调整和修改。
-
目前前端封装小组已经封装了一多半的 ElementUI 组件,一些组件在封装中发现,部分封装出来的组件在后期更换UI库时不时很灵活,在不调整业务代码的情况下,支持不同的UI库组件切换封装层的代码需要支持两种情况,或基于新的UI库组件用法修改调用参数进行匹配处理,这部分的后期在更新UI库时组件的修改代价还是很高的。
GitHub 源码地址
https://github.com/gywgithub/element2-package
网友评论