在Vue前端项目中,我这里主要是基于Vue+Element的开发,大多数情况下,我们利用Element的表格组件就可以满足大多数情况的要求,本篇随笔针对表格的展示和编辑处理,综合性的介绍几款表格组件的展示和处理效果,其中包括Element的el-table组件,以及其他第三方类组件,如vue-easytable、vue-willtable,以及vxe-table,针对性的对比相关的差异。
1、el-table表格组件
这个表格组件也是非常好用的展示数据的组件,提供了很多属性设置,表格列的模板定义可以进行各种各样的转义和处理,是我们使用Element组件经常用到的组件之一。
简单的界面效果如下所示。
它的简单界面代码如下所示,主要就是提供列的定义。
<template>
<el-table:data="tableData"stripe style="width: 100%">
<el-table-columnprop="date"label="日期"width="180"> </el-table-column>
<el-table-columnprop="name"label="姓名"width="180"> </el-table-column>
<el-table-columnprop="address"label="地址"> </el-table-column>
</el-table>
</template>
而数据这是一个对象集合,里面对应各种属性记录,如下所示。
<script>exportdefault{
data() {return{
tableData: [{
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 弄'}]
}
}
}</script>
不过一般实际使用的表格比这个会复杂很多,会在列之中提供很多转义信息展示,如下界面效果所示
或者
我们来看看表格头部和表格列的相关定义来进行解析。
<el-tablev-loading="listLoading":data="list"border fit stripe highlight-current-row
:header-cell-style="{background:'#eef1f6',color:'#606266'}"@selection-change="selectionChange"@row-dblclick="rowDbclick"@sort-change="sortChange">
listLoading用来 展示/隐藏 加载中的状态
list则是提供给表格数据处理的数据源
selectionChange这是选中/取消勾选框的事件触发
rowDbclick是双击表格行出现的事件响应
sortChange是排序表头出现的事件处理
另外,表格数据往往涉及到分页信息,那么必须和分页控件一起使用
<!--分页部分-->
<divclass="block"style="height:70px;">
<el-pagination:current-page="pageinfo.pageindex":page-size="pageinfo.pagesize":total="pageinfo.total":page-sizes="[10,20,30,40]"layout="total, sizes, prev, pager, next"@size-change="sizeChange"@current-change="currentChange" />
</div>
其中分页组件中涉及到pageinfo对象,包括当前页码和每页的数据记录数量,以及对每页数据大小变化事件sizeChange、页码变化的事件currentChange的处理。
因此我们在<script>中定义相关的变量和方法。
export default{
components: {},//常见组件已经在main.js中挂载
data () {return{
listLoading:false, //列表加载状态
list: [], //页面列表数据
pageinfo: {//分页条件
pageindex: 1,
pagesize:20,
total:0},
listSelection: [],//选中记录
sorting: null, //排序条件
获取数据的事件getlist中,我们主要就是根据条件获取数据记录,并赋值给list对象即可。
而其他相应的事件如下定义所示
search () { //查询列表处理
this.pageinfo.pageindex = 1;//重置为第一页
this.searchForm.pid = null;//重置选择类型
this.getlist()
},
resetSeachForm (formName) {//重置查询条件处理
this.$refs[formName].resetFields();this.search()
},
sortChange ({ column, prop, order }) {var direction = (order === 'ascending') ? ' ASC' : ' DESC'
this.sorting = !this.isEmpty(prop) ? (prop + direction) : null
this.getlist()
},
sizeChange (val) {//页面大小变化处理
//console.log(`每页 ${val} 条`);
this.pageinfo.pagesize =val;this.getlist()
},
currentChange (val) {//页码变化处理
//console.log(`当前页: ${val}`);
this.pageinfo.pageindex =val;this.getlist()
},
selectionChange (val) {//选中记录
this.listSelection =val;
},
rowDbclick (row, column) {//列表单击处理
var id =row.idthis.showView(id);
},
这样我们就是实现了对数据的分页处理,和相关的事件处理。剩下的就是对记录列内容的转义处理了,这个通过HTML的代码进行处理即可。
常规的内容处理如下所示。
<el-table-columnalign="center"label="名称"sortable="custom"prop="name"min-width="150">
<templateslot-scope="scope">{{ scope.row.name }}</template>
</el-table-column>
如果我们需要进行转义,在这里面处理判断就可以了,非常方便。
<el-table-columnalign="center"label="可见"sortable="custom"prop="visible"width="80">
<templateslot-scope="scope">
<el-tagv-if="scope.row.visible"type="success"effect="dark">可见</el-tag>
<el-tagv-else type="danger"effect="dark">隐藏</el-tag>
</template>
</el-table-column>
或者通过formater的函数进行内容的转义处理。
<el-table-columnalign="center"label="创建时间"width="160"sortable="custom"prop="createTime":formatter="timeFormat" />
也可以使用filter进行内容转义
<el-table-columnalign="center"label="商品类型"width="120"prop="ProductType">
<templateslot-scope="scope">
<el-tagtype="danger"> {{ scope.row.ProductType | productTypeFilter }}</el-tag>
</template>
</el-table-column>
如果我们需要添加表格列的操作处理,那么添加对应的按钮即可,通过获取对应记录的标识,来进行相关记录的操作即可。
<!--表格行操作按钮-->
<el-table-columnalign="center"label="操作"width="110">
<templatescope="scope">
<el-row>
<el-button-group>
<el-tooltipeffect="light"content="查看"placement="top-start">
<el-buttonicon="el-icon-search"type="success"circle size="mini"@click="showView(scope.row.id)" />
</el-tooltip>
<el-tooltipeffect="light"content="编辑"placement="top-start">
<el-buttonicon="el-icon-edit"type="primary"circle size="mini"@click="showEdit(scope.row.id)" />
</el-tooltip>
<el-tooltipeffect="light"content="删除"placement="top-start">
<el-buttonicon="el-icon-delete"type="danger"circle size="mini"@click="showDelete(scope.row.id)" />
</el-tooltip>
</el-button-group>
</el-row>
</template>
</el-table-column>
Element的表格组件功能虽然很好,不过它的特点是展示处理,并不是很适合进行直接内容的编辑处理,有些人通过变量标识模板的方式控制编辑界面的展示,不过总体太复杂,不方便使用。
2、vue-easytable表格组件
vue-easytable表格组件地址:
npm安装:npm install vue-easytable -S
这个组件相对于Element的表格el-table来说,它的HTML代码比较少,适用于简单快捷的表格数据展示。
简单使用代码如下所示
<ve-table:columns="columns":table-data="tableData" />
一般它的使用代码如下所示(配合分页数据展示)
<ve-tablerow-key-field-name="id":checkbox-option="checkboxOption":columns="columns":table-data="list":fixed-header="true":border-around="true":border-x="true":border-y="true" />
<!--分页部分-->
<divclass="block"style="height:70px;">
<el-pagination:current-page="pageinfo.pageindex":page-size="pageinfo.pagesize":total="pageinfo.total":page-sizes="[10,20,30,40]"layout="total, sizes, prev, pager, next"@size-change="sizeChange"@current-change="currentChange" />
常见的界面效果如下所示
一般我们需要在JS中定义列的信息,它的类型可以是expand、checkbox、radio几种之一,默认是字符串方式。
当前列类型: "expand":行展开;"checkbox":行多选;"radio":行单选
columns: [//表列定义
{
field:'',
key:'a',
type:'checkbox',
title:'',
width:50,
align:'center'},
{
field:'name',
key:'name',
title:'姓名',
width:120,
columnAlign:'center'},
这个列的定义除了field外,还需要一个Key的标识,不能为空,一般保留位field的值即可。
如果我们需要进行内容的转义处理,可以使用 renderBodyCell 函数进行转义处理,如下所示。
{
field:'sex',
key:'sex',
title:'性别',
width:120,
columnAlign:'center',
renderBodyCell: ({ row, column, rowIndex }, h)=>{
const text=row[column.field];//return <input style="width:100%" value={text}></input>;
let html = null
if (text === '男') {
html= <el-tag type='primary'>{text}</el-tag>
} else{
html= <el-tag type='success'>{text}</el-tag>
}return(<div>{html}</div>
)
}
},
数据的处理,和我们前面介绍的类似,就是通过分页条件的方式进行查询分页,获得数据后赋值给对应列表即可。
//获取列表,绑定到模型上,并修改分页数量
this.listLoading = truetestUser.GetAll(param).then(data=>{
console.log(data.result.items)this.list =data.result.itemsthis.pageinfo.total =data.result.totalCountthis.listLoading = false})
通过 row-key-field-name="id" :checkbox-option="checkboxOption" 代码的处理,可以实现选中记录的操作。
checkboxOption: {//row select事件
selectedRowChange: ({ row, isSelected, selectedRowKeys }) =>{
console.log(row, isSelected, selectedRowKeys);
},//selected all事件
selectedAllChange: ({ isSelected, selectedRowKeys }) =>{
console.log(isSelected, selectedRowKeys);
}
},
这个表格组件也主要是进行展示,没有直接编辑的处理操作,不过它的特点是快速展示数据,转义的话操作起来会费劲一些,它主要就是通过jsx的方式进行转义处理的,感觉没有在HTML上直接判断的快捷明了。
3、vue-willtable表格组件(可直接编辑)
以上两个表格组件,都没有涉及到编辑的操作,有时候我们在一些表格中希望给客户直接录入数据的场景。
如果采用el-table的方式来处理,非常不直观,也不易处理,因此引入第三方组件的方式来实现数据的直接录入就比较好 了。
官方案例界面效果如下所示。
表格提供日期,数值、下拉列表,字符串等几种常见方式的录入。
总体上录入没有什么问题,不过对于组件的更新好像有时候有些问题,毕竟github上星星不是很多的项目。
我在这个基础上进行了案例的测试,界面效果如下所示。
主从表展示界面效果
以及表格查询分页处理和录入界面效果
<divclass="willtable_wrapper">
<vue-willtableref="table"v-model="list":columns="columns":row-height="38":cell-class-name="cellClassName" />
</div>
字段定义的JS代码如下所示。
获取数据的JS代码如下所示
//获取列表,绑定到模型上,并修改分页数量
this.listLoading = truetestUser.GetAll(param).then(data=>{this.$refs.table.setData(data.result.items)this.pageinfo.total =data.result.totalCountthis.listLoading = false})
不过分页的话,切换页面大小会导致刷新显示有些问题 ,部分空白,首次显示倒是没有问题。
4、vxe-table表格组件(可直接编辑)
vxe-table是github上星星超过4k+的开源组件,这个表格不论是展示数据,以及编辑的处理,都堪称大能之作,非常方便强大。
vxe-table地址:
https://xuliangzhan_admin.gitee.io/vxe-table/#/table/start/install
https://github.com/x-extends/vxe-table
我们来看看它的常规使用代码,以及界面效果
如果需要录入新记录,通事件处理添加一个行即可。
vxe-table的使用HTML代码和Element的el-table类似,通过HTML声明的方式进行定义,如下所示。
<vxe-tableref="xTable"border show-overflow keep-source resizable show-overflow :data="list":edit-config="{trigger: 'click', mode: 'row', showStatus: true}">
<vxe-columntype="seq"width="60" />
<vxe-columnfield="name"title="姓名":edit-render="{name: 'input', attrs: {type: 'text'}}" />
<vxe-columnfield="sex"title="性别":edit-render="{name: '$select', options: sexList}" />
<vxe-columnfield="emailAddress"title="邮件地址":edit-render="{name: 'input', attrs: {type: 'text', placeholder: '请输入邮件地址'}}" />
<vxe-columnfield="marriage"title="婚姻状况":edit-render="{name: '$select', options: marriageList, props: {multiple: false}}" />
<vxe-columnfield="status"title="状态":edit-render="{name: '$select', options: StatusList, props: {multiple: false}}" />
<vxe-columnfield="height"title="身高":edit-render="{name: '$input', props: {type: 'float', digits: 2}}" />
<vxe-columnfield="birthDate"title="出生日期":edit-render="{name: '$input', props: {type: 'date', placeholder: '请选择日期'}}":formatter="formatDate" />
</vxe-table>
而数据的获取展示方式,和上面代码操作一样
//获取列表,绑定到模型上,并修改分页数量
this.listLoading = truetestUser.GetAll(param).then(data=>{
console.log(data.result.items)this.list =data.result.itemsthis.pageinfo.total =data.result.totalCountthis.listLoading = false})
其实我们主要关注它的数据的新增,以及保存处理即可,插入或者移除记录的处理如下代码所示。
async insertEvent () {
const $table= this.$refs.xTable
const newRecord={}
const { row: newRow }=await $table.insert(newRecord)
await $table.setActiveRow(newRow)
},
async removeSelectEvent () {
const $table= this.$refs.xTable
await $table.removeCheckboxRow()
},
async removeRowEvent (row) {
const $table= this.$refs.xTable
await $table.remove(row)
},
如果是保存,那么需要获取数据记录的更新、删除、新增几个集合的情况,然后统一通过后端进行辨别处理即可。
async saveEvent () {
const $table= this.$refs.xTable
const { insertRecords, removeRecords, updateRecords }=$table.getRecordset()if (insertRecords.length <= 0 && removeRecords.length <= 0 && updateRecords.length <= 0) {this.msgSuccess('数据未改动!')return}
const errMap= await $table.validate().catch(errMap =>errMap)if(errMap) {return}this.listLoading = true
try{
const body={ insertRecords, removeRecords, updateRecords }
console.log(body)///await XEAjax.post('https://api.xuliangzhan.com:10443/demo/api/pub/save', body)
//await this.loadList()
this.msgSuccess(`操作成功,新增 ${insertRecords.length} 条,更新 ${updateRecords.length} 条,删除 ${removeRecords.length} 条`)
}catch(e) {if (e &&e.message) {this.msgSuccess(e.message)
}
}this.listLoading = false},
通过引用对象的
getRecordset
我们可以获得相关新增、更新、删除的集合,然后通过自己的逻辑处理数据即可。
该表格组件提供了很多方便的处理案例,我们可以通过学习方式进行参考即可。
以上就是几款表格组件的效果,对比它们,一般来说,我们还是倾向于使用el-table的内置表格组件来展示数据,而且也可以通过我们的代码生成工具Database2sharp进行vue界面的快速生成,然后微调即可,而对于数据直接编辑的处理,则建议通过使用vxe-table的组件的方式进行处理,它提供了非常多强大的功能,可以满足我们直接录入数据的处理操作。