造轮子的目的,是为了更爽的开发。当然,大家都在说,不要重复造轮子,只是我没有找到同样的轮子,才自己造了一个。也看到有人封装过 Element 的 Table,只是感觉封装的太浅,不够深入。下面说的这个,可能也是你需要的。
全文共 2388 字,读完需 6 分钟。
同步发表于知乎专栏:前端微志
惯例,开始之前,贴个Github地址,求 star😂。点击 阅读原文 去 GitHub 瞅瞅。
https://github.com/zollero/el-search-table-pagination
用 Vue 做前端开发的同学,肯定都听说过 Element UI (下文中称为 Element)这个由 饿了么前端团队 开发的基于 Vue 的 UI 组件库。
而用 Element 做的最多的就是 Table,且这个 Table 需要支持分页 和 搜索查询,且还会有一些操作按钮,用来处理数据。
前奏
系统中有很多页面都用到了 Element 的 Form, Table, Pagination 组件。当这种页面多了之后,就会出现很多重复代码,使得业务代码的占比不高,需要花更多的时候去维护非业务代码,效率不高,也有一些风险。
写多了之后,我决定封装一个通用组件,可以让我只用关注业务代码就可以。
一般情况下,我们使用 Element 的 Table,Pagination 组件 写一个简单的页面,会像下面这样。
可以看出,要写这样一个页面,有一些东西需要处理,如:默认加载数据,分页切换等操作,都是需要单独处理。一般,在 Table 上面,还有一个搜索框,里面有几个搜索条件的输入框用来辅助搜索展示数据。这些操作步骤,是重复性的,再新建一个页面,都要再写一遍。
这样一个没效率的事情,怎么能忍?所以 el-search-table-pagination 应运而生,帮助开发者更好地用 Element 编写包含 Form,Table 和 Pagination 组件的页面。
还拿上图中的功能为例,用 el-search-table-pagination 重写之后,是下面这样的。
重构之后,代码简洁很多,将通用代码抽离,开发者只需要关注业务代码即可,不用再维护很多重复代码。
特性
上面例子中说了 el-search-table-pagination 组件的简单使用,为了让它保持一定的通用性,做了一些封装,有一些细节你可能需要知道。
-
默认使用 axios 查询远程数据,当然你也可以配置一个封装之后的 axios(你可能会设置一些 interceptor)
-
最大化地像可配置化迈进,让你尽可能少的写 html,最大化地支持 Element 中的特性(持续更新)
-
同样可以配置搜索框中的搜索条件,如:输入框,下拉框,日期选择框、日期范围选择框等(后续会支持更多form item)
-
除了支持远程数据的分页查询展示,还支持本地数据的分页及查询过滤
-
CSS 样式使用 Element 中的样式,如果需要修改默认样式,按原来的方式做就行
-
table-column 中如果需要转换结构,可以使用 slot 来嵌套
使用
使用方法跟 Element 类似。
如果你想直接用,没有自己封装 axios,可以这样:
import Vue from 'vue'
import ElSearchTablePagination from 'el-search-table-pagination'
// Default use axios as HTTP tool
Vue.use(ElSearchTablePagination)
复制代码
如果你有自己封装 axios,可以在使用的时候,默认传入,这样将使用你传入的 axios 实例调用远程接口:
import Vue from 'vue'
import ElSearchTablePagination from 'el-search-table-pagination'
// 你自己封装了 axios
import axios from './utils/axios'
Vue.use(ElSearchTablePagination, {
axios
})
复制代码
当然,你也可以使用 CDN,在 html 文件中使用 script 标签来引用。
在 CODEPEN 上建了两个 DEMO 分别展示 本地数据 和 远程数据。DEMO 地址如下:
本地数据:
https://codepen.io/zollero/pen/wPRqYX
远程数据:
https://codepen.io/zollero/pen/xPmXBp
中文文档在此,欢迎打醒:
https://github.com/zollero/el-search-table-pagination/blob/HEAD/docs/zh_CN.md
注意事项
转换 table-column 内容的方式
很多时候,接口中字段的值,需要做转换才能展示,在 columns 中 column 的属性,提供了几种方式来帮你转换。
一、filter
如果你只需要使用 filter 转换这个字段的值,把 filter 的名称赋给filter就可以了,注意:只有注册在Vue 全局的 filter才有效
// 使用 filter 属性转换内容
const columns = [
{
prop: 'updateTime',
label: '更新时间',
width: 110,
filter: 'formatDate'
},
...
]
复制代码
上面用到的 filter 需要注册在 Vue 全局内才有效。
// 需要提前注册好这个 filter
Vue.filter('formatDate', (value) => {
if (!value) return '';
let d = new Date(value);
return d.getFullYear() + '-'
+ (d.getMonth() + 1) + '-'
+ d.getDate()
})
复制代码
二、render
如果你想通过一个函数来转换一下,就把函数设置给 render 属性吧,记得将最终的值 return 出来。
// 使用 render 属性转换内容
const columns = [
{
prop: 'price',
label: '价格
minWidth: 130,
render: row => `${row.price} 元`
},
...
]
复制代码
三、slotName
如果内容需要一段 HTML 重新填充到 table 内,这种方式最直观。首先在 el-search-table-pagination 标签内定义一个 slot,然后将 slot 的值赋给 slotName 即可。
// 使用 slotName 属性来转换内容
const columns = [
{
label: '预览',
prop: 'url', // 此时为选填
width: 380,
slotName: 'preview-column'
},
...
]
复制代码
上面用到的 slot: preview-column 需要在 el-search-table-pagination 标签内声明,如下:
// 声明 slot,这种方式支持负责内容渲染
// 代码中 slot-scope 属性是 Vue v2.5.x 之后的属性
// 如果你的 Vue 版本低于 v2.5.x,请使用 slot
<el-search-table-pagination
:columns="columns"
... >
<template slot="preview-column"
slot-scope="scope">
<img width="350px"
:src="scope.row.url" />
</template>
</el-search-table-pagination>
复制代码
操作列
很多场景下,都会需要在 Table 右侧添加一个 操作列,操作列里需要一些按钮,用来处理数据交互等。
这时候,你可以在 el-search-table-pagination 标签下使用 slot: append,可以在 Table 右侧添加一个 操作列。示例如下:
<el-search-table-pagination
:columns="columns"
... >
<el-table-column slot="append">
<template slot-scope="scope">
<div>
<el-button type="success">
通过
</el-button>
<el-button type="danger">
退回
</el-button>
</div>
</template>
</el-table-column>
</el-search-table-pagination>
复制代码
Form 的配置化
插件提供了对 Form 表单的可配置实现,只需要提供 form-options 属性即可,其中 formOptions.forms 属性是一个数组,用来配置多个 form item。
forms 定义的 prop 属性的值,是会被传给后端接口的参数名。当然,传给后端接口的时候,还会带上分页参数。
首先需要注意的是属性:form.itemType
itemType 表示 from item 的类型,目前支持四种:input,select,date 和 daterange,且默认是 input。对应的是 Element 中的输入框,下拉框,日期选择框,日期范围选择框。
一、input
输入框比较简单,只需要设置好一下几个字段即可:
const forms = [
{
prop: 'url',
label: 'url地址',
size: 'small', // 选填
itemType: 'input'
},
...
]
复制代码
二、select
下拉框相对复杂点,除了要配置 input 的那些参数,还有一些参数需要注意。
由于,下拉框的下拉选项的值可能是代码里写死的,也可能是从接口中获取的。所以,针对这两种提供了两种写法。
// 下拉选项的值是代码里写死的
const forms = [
{
prop: 'status',
label: '状态',
size: 'small',
itemType: 'select',
options: [{
value: '',
label: '全部'
}, {
value: '1',
label: '通过'
}, {
value: '2',
label: '退回'
}]
},
...
]
// 下拉选项的值有部分是代码写死的
// 有部分是从接口中获取的
const forms = [
{
prop: 'name',
label: '名称',
size: 'small',
itemType: 'select',
options: [{
value: '',
label: '全部'
}],
// fetch 和 url 可任选一项
// selectUrl: 'http://x.com/a'
selectFetch: axios.get('http://x.com/a')
},
...
]
复制代码
三、date
这种类型也比较简单,跟 input 非常类似。
const forms = [
{
prop: 'date',
label: '日期',
size: 'small',
editable: false,
itemType: 'date',
placeholder: '请选择日期'
},
...
]
复制代码
四、daterange
daterange 是针对那种选择日期范围的情况,因为经常遇到接口中要求传 开始日期 和 结束日期 两个字段,daterange 就是为这种场景而生的。
与前面几种类型不同的是,daterange 的 prop 属性需要传递一个数组,数组的是分别是 开始日期 和 结束日期 的字段值。
const forms = [
{
prop: ['dateStart', 'dateEnd'],
label: '日期范围',
size: 'small',
editable: false,
itemType: 'daterange',
placeholder: '请选择日期范围'
},
...
]
复制代码
目前,只支持这四种类型,后续会添加更多类型支持。
结尾
插件已经发布到 npm 上了,大家可以直接下载使用,或者去 GitHub 上扔个 PR 或 ISSUE,不管怎样,欢迎来个star😂。
本文只是简单介绍了插件的功能,更多功能,还请参考 文档。
npm 包地址:
https://www.npmjs.com/package/el-search-table-pagination