小颖前段时间做的项目里需要实现一个功能:表格可以行内编辑,并且表格的部分列是固定的,部分列随着右上角勾选的可显示列的变化而变化,在右侧我勾选了那些列,表格才能显示那些列,如果我没有勾选则不显示。
具体效果如图所示:
具体代码:
小颖用的vue+Ant Design of Vue
html:
<template> <div class="table-dynamic-column"> <p class="txt-right"> <a-dropdown :trigger="['click']"> <i class="fa fa-bars ant-dropdown-link"></i> <a-menu slot="overlay"> <a-menu-item key="1" :disabled="true" class="have-disabled"> <a-checkbox :indeterminate="indeterminate" @change="selectAllFun" :checked="checked">全选/反选 </a-checkbox> </a-menu-item> <a-menu-item key="2" :disabled="true" class="have-disabled"> <a-checkbox-group v-model="showColumn" @change="hideColumnChange()"> <div class="dropdown-menu-item-tem" v-for="(item,index) in movingColumns" @click="hideColumnFun(index)" :key="index"> <a-checkbox :value="item.dataIndex"> <span class="hide-column-tem">{{item.title}}</span> </a-checkbox> </div> </a-checkbox-group> </a-menu-item> </a-menu> </a-dropdown> </p> <a-table :columns="columns" :dataSource="data" bordered> <template v-for="col in editColumnDt" :slot="col" slot-scope="text, record" > <div :key="col"> <a-input v-if="record.editable" style="margin: -5px 0" :value="text" @change="e => handleChange(e.target.value, record.key, col)" /> <template v-else>{{text}}</template> </div> </template> <template slot="operation" slot-scope="text, record"> <div class="editable-row-operations" v-if="columns.length>3"> <span v-if="record.editable"> <a @click="() => save(record.key)">Save</a> <a-popconfirm title="Sure to cancel?" @confirm="() => cancel(record.key)"> <a>Cancel</a> </a-popconfirm> </span> <span v-else><a @click="() => edit(record.key)">Edit</a></span> </div> <div v-else>暂无操作</div> </template> </a-table> </div> </template>
js:
<script> const columns = [ { title: 'name', dataIndex: 'name', scopedSlots: { customRender: 'name' }, }, { title: 'age', dataIndex: 'age', scopedSlots: { customRender: 'age' }, }, { title: 'operation', dataIndex: 'operation', scopedSlots: { customRender: 'operation' }, }, ]; const data = []; for (let i = 0; i < 100; i++) { data.push({ key: i.toString(), name: `Edrward ${i}`, age: 32, phone: 15388646322, address: `London Park no. ${i}`, }); } export default { name: "tableDynamicColumn", data() { this.cacheData = data.map(item => ({ ...item })); return { checked: true, indeterminate: false, data, columns, editColumnDt: [],//可编辑的列 movingColumns: [],//动态显示列 showColumn: [],//不隐藏的列 hideColumnIndex: null,//当前点的那个复选框 }; }, mounted() { this.getDynamicColumn() }, methods: { //获取动态列信息 getDynamicColumn(){ // 调接口获取动态列 const that = this const responseData = [ { title: 'address', dataIndex: 'address', scopedSlots: {customRender: 'address'}, }, { title: 'phone', dataIndex: 'phone', scopedSlots: {customRender: 'phone'}, } ] const newData = [...responseData] newData.forEach(function (item, index) { that.editColumnDt[index] = item.dataIndex that.showColumn[index] = item.dataIndex }) this.movingColumns = newData const operation = this.columns.splice(2, 1) this.columns = this.columns.concat(newData) this.columns = this.columns.concat(operation) }, handleChange(value, key, column) { const newData = [...this.data]; const target = newData.filter(item => key === item.key)[0]; if (target) { target[column] = value; this.data = newData; } }, edit(key) { const newData = [...this.data]; const target = newData.filter(item => key === item.key)[0]; if (target) { target.editable = true; this.data = newData; } }, save(key) { const newData = [...this.data]; const target = newData.filter(item => key === item.key)[0]; if (target) { delete target.editable; this.data = newData; this.cacheData = newData.map(item => ({ ...item })); } }, cancel(key) { const newData = [...this.data]; const target = newData.filter(item => key === item.key)[0]; if (target) { Object.assign(target, this.cacheData.filter(item => key === item.key)[0]); delete target.editable; this.data = newData; } }, //全选/反选 selectAllFun(e){ this.checked = e.target.checked this.indeterminate = false if(e.target.checked){//全选 this.showColumn = this.movingColumns.map(function (item) { item.hideCol = false return item.dataIndex }) const operation = this.columns.splice(2, 1) this.columns = this.columns.concat(this.movingColumns) this.columns = this.columns.concat(operation) }else {//反选 this.showColumn = [] this.movingColumns.map(function (item) { item.hideCol = true }) this.movingColumnFun() } }, //右侧显示隐藏的复选框的change事件 hideColumnChange(){ this.indeterminate = false this.checked = false const newData = [...this.showColumn] //全选 if (newData.length === this.movingColumns.length) { this.checked = true } //半选样式 if (newData.length !== 0 && newData.length < this.movingColumns.length) { this.indeterminate = true } const index = this.hideColumnIndex const target = newData.filter(item => this.movingColumns[index].dataIndex === item)[0]; if (target) { this.$set(this.movingColumns[index], 'hideCol', false) } else { this.$set(this.movingColumns[index], 'hideCol', true) } this.movingColumnFun() }, movingColumnFun(){ const _movingColumns = this.movingColumns.filter(item => { if (!item.hideCol) { return item } }) const operation = this.columns.splice(this.columns.length - 1, 1)//截取操作列 const _columns = this.columns.slice(0, 2)//先回归固定列 this.columns = _columns.concat(_movingColumns) this.columns = this.columns.concat(operation) }, //隐藏列单独勾选 hideColumnFun(index) { this.hideColumnIndex = index } } } </script>
css:
<style scoped> .editable-row-operations a { margin-right: 8px; } .txt-right{ padding: 20px 5px 10px 0; } </style>
具体实现请移步:小颖Git