需求背景
用户想对表格列进行宽度、位置、是否显示等进行操作,方便查看自己想看到的数据,并且希望这些设置能够记录下来,即使关闭浏览器,或换其他电脑再次访问系统时,表格显示的列依然是之前配置的结果。
解决思路
由于用户希望换了电脑访问系统还是能显示之前表格操作效果,这里使用localstorage显然是不行的,需要后台提供接口将操作后的表头数据存到数据库中。
由于系统表格表头涉及到多个层级,以及需自定义列内容,这里使用了jsx渲染表头数据,在开发业务功能时,只需维护好表头数据就行,不需要书写表格dom结构。
实现
功能点:
- 调整列宽
- 恢复默认表头
- 设置 全部/单个 列 显示/隐藏
- 设置固定列
- 列文本对齐方式
- 调整列顺序
定义表头数据
表头数据必须定义u_id字段,并且要保证u_id的唯一性,因为从数据库提取出来表头数据根据u_id与本地表头数据比对合并
data(){
return {
cols: [{
u_id: '0',
label: '日期',
prop: 'date',
render(h){
return h('el-table-column', {
props: {
...this
},
scopedSlots: {
default: (props) => {
const { row } = props
return <span><i class="el-icon-date"/>{row.date}</span>
}
}
})
}
}, {
u_id: '1',
label: '配送信息',
children: [{
u_id: '10',
label: '姓名',
prop: 'name',
width: '120'
}, {
u_id: '11',
label: '地址',
children: [{
u_id: '110',
label: '省份',
prop: 'province',
width: '120'
}, {
u_id: '111',
label: '市区',
prop: 'city',
width: '120'
}, {
u_id: '112',
label: '地址',
prop: 'address',
width: '300'
}, {
u_id: '113',
label: '邮编',
prop: 'zip',
width: '120'
}]
}]
}]
}
}
复制代码
定义公共方法
- 深拷贝方法
由于表头数据里面可能会有方法属性,不要使用JSON.parse(JSON.stringify(obj))的方式去拷贝数据,这样会使方法属性丢失
export function deepClone(obj) {
let newObj = null
if (typeof obj === 'object' && obj !== null) {
newObj = obj instanceof Array ? [] : {}
for (let i in obj) {
newObj[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i]
}
} else {
newObj = obj
}
return newObj
}
复制代码
- 创建id/删除id方法
export function createId(arr, defaultId = '_'){
arr.forEach((item, index) => {
item.id = defaultId + index
if(defaultId != '_') item.p_id = defaultId
if(item.children && item.children.length) createId(item.children, item.id)
})
return arr
}
export function removeId(arr){
arr.forEach(item => {
item.id && delete item.id
item.p_id && delete item.p_id
if(item.children && item.children.length) removeId(item.children)
})
return arr
}
复制代码
- 一维转多维/多维转一维方法
export function treeToArray(arr){
return arr.reduce((acc, cur) => {
if(Array.isArray(cur.children)){
const copyCur = { ...cur }
delete copyCur.children
return acc.concat(copyCur, treeToArray(cur.children))
}else{
return acc.concat(cur)
}
}, [])
}
export function arrayToTree(arr) {
let temp = {}
let tree = {}
arr.forEach(item => {
temp[item.id] = item
})
let tempKeys = Object.keys(temp)
tempKeys.forEach(key => {
let item = temp[key]
let pid = item.p_id
let pItem = temp[pid]
if(pItem){
if(!pItem.children){
pItem.children = []
}
pItem.children.push(item)
}else{
tree[item.id] = item
}
})
return Object.keys(tree).map(key => tree[key])
}
复制代码
- 查找多维数组里某个元素的所有子元素方法
export function findChildLen(arr, id, dLen){
handler(id)
function handler(id){
let temp = []
arr.forEach(item => {
if(item.p_id == id){
dLen++
temp.push(item)
}
})
temp.forEach(item => {
handler(item.id)
})
}
return dLen
}
复制代码
定义DynamicTable组件
作用:该组件主要实现渲染table,调用接口获取/保存表头数据,调整列宽等功能 组件支持接收属性:
- el-table属性
- cols:表头数据
- tableflag:模块名,用于将数据存储时,区分是哪一个页面的数据
多层级表头
表格通过vue的render函数以jsx方式渲染,并定义renderCol方法递归多层级表头。 列自定义内容 有时列的内容需要特殊处理,例如在日期前加个图标
我们可以在表头数据cols中定义render属性方法,接收h函数(vm.$createElement),去渲染虚拟dom
render() {
return (
<div class="dt-container">
<div class="dt-container-box">
<el-table
ref="table"
props={this.$attrs}
on-header-dragend={this.headDragend}
>
{this.renderCol(this.columns)}
</el-table>
</div>
<ColumnSetting
ref="csRef"
defaultTableHeadData={this.cols}
tableHeadData={this.tableHeadData}
columns={this.columnInfo}
onChangeColumn={this.handleColumnChange}
/>
</div>
);
},
methods: {
// 渲染列
renderCol(arr) {
return arr.map((col) => {
const cols = this.getShowColumn(col.children || []); //过滤掉不显示的列
if (col.render) return col.render(this.$createElement);
if (cols.length == 0) {
return <el-table-column props={col}/>;
}
return (
<el-table-column props={col}>{this.renderCol(cols)}</el-table-column>
);
});
},
}
复制代码
表头数据cols
{
u_id: '0',
label: '日期',
prop: 'date',
render(h){
return h('el-table-column', {
props: {
...this
},
scopedSlots: {
default: (props) => {
const { row } = props
return <span><i class="el-icon-date"/>{row.date}</span>
}
}
})
}
}
复制代码
在页面挂载时调用接口获取之前配置的表头数据,与初始的数据进行合并
// 从服务器获取表头数据
getHeadDataByData() {
let para = {
pageCode: `${moduleKey}_${this.tabelflag}`,
};
fetchFieldsByUser(para).then((res) => {
const data = res.data || {};
const columns = data.columns || "[]";
this.mergeHeadData(JSON.parse(columns));
});
},
// 本地表头数据和服务器存储数据合并
mergeHeadData(uiData) {
let tableHeadData = createId(deepClone(this.tableHeadData));
// 添加索引,用于排序
tableHeadData = createIndex(tableHeadData);
uiData = createIndex(uiData);
// 多维转一维
let uiData_temp = treeToArray(uiData);
let tableHeadData_temp = treeToArray(tableHeadData);
// 以本地数据为准,合并数据
uiData_temp.forEach((item) => {
tableHeadData_temp.forEach((i) => {
if (item.u_id == i.u_id) {
Object.assign(i, item);
return;
}
});
});
// 根据索引排序
tableHeadData_temp = tableHeadData_temp.sort((a, b) => {
let idx1 = a.idx;
let idx2 = b.idx;
if (idx1 < idx2) {
return -1;
} else if (idx1 > idx2) {
return 1;
} else {
return 0;
}
});
this.$set(this, "tableHeadData", []);
this.$nextTick(() => {
this.$set(
this,
"tableHeadData",
arrayToTree(deepClone(tableHeadData_temp))
);
// 解决设置fixed样式错乱问题
this.$refs.table.doLayout()
});
function createIndex(arr) {
arr.forEach((item, index) => {
item.idx = index;
if (item.children && item.children.length) {
createIndex(item.children);
}
});
return arr;
}
},
复制代码
在el-table上绑定headerDragend方法,更新表头数据列宽
// 改变列宽
headDragend(newWidth, oldWidth, column) {
let findCol = findItem(column.property, this.tableHeadData);
if (findCol) findCol.width = newWidth + "";
this.submitTableHeadData(this.tableHeadData);
function findItem(prop, arr) {
for (let item of arr) {
if (item.prop == prop) return item;
if (item.children && item.children.length) {
let _item = findItem(prop, item.children);
if (_item) return _item;
}
}
}
}
复制代码
定义列设置弹窗组件(ColumnSetting)
组件支持接收属性
- tableHeadData:表头数据
- defaultTableHeadData:初始表头数据,没配置过的,用于恢复默认时试用
- columns:el-table的组件的表头数据,通过this. children[0].columns获得,主要是为了获取列的真实宽度
功能
- 恢复默认,将表头数据还原成初始数据
- 全部显示/隐藏
- 固定列,只能在没有父层级的列设置固定列,否则会出现样式错乱,要注意的是,在设置固定列时,表头最外层没有设置宽度的话,表格样式会出现错位的情况,这时就需要通过props的columns获取el-table真实的列宽,去计算出最外层的宽度并设置
- 对齐方式,只能在没有子节点的列才能设置,否则是不生效的
- 列显示,设置当前列是否显示
- 调整列顺序,通过使用sortablejs插件实现拖拽排列。Sortablejs的用法可参考文档,这里主要用了onStart(开始拖拽)、onEnd(结束拖拽)两个属性方法
在onStart中,需先备份列数据,主要用于拖拽的列越出当前层级时,恢复到拖拽前的数据;以及备份当前所有展开行的数据,当拖拽结束,列数据更新时,表格的数据会被刷新,展开行会收缩,需设置回拖拽前的状态。当前展开行的数据可通过监听el-table的expand-change事件设置。
// 保存展开行,解决数据刷新时,行全部收缩问题
handleExpandChange(row, expanded) {
if (expanded) {
this.rowKeys.push(row.id);
} else {
let index = this.rowKeys.indexOf(row.id);
this.rowKeys.splice(index, 1);
}
}
复制代码
在onEnd中,可以获取到oldIndex(拖拽前的索引)、newIndex(拖拽后的索引),通过这两个参数去得到拖拽的列数据,以及插入的列数据,判断它们的p_id(父级id)是否相同,不同时,则表示拖拽越层级,恢复回拖拽前的数据;相同时,会去获取拖拽的列数据的所有子数据(包括当前拖拽的数据),插入到拖拽后的位置。
onEnd: ({ newIndex, oldIndex }) => {
let table = Object.assign([], this.tableData);
let newTable = treeToArray(table); //多维转一维
const sourceItem = newTable[oldIndex];
const targetItem = newTable[newIndex];
//判断拖拽是否在同级中操作
if (sourceItem.p_id !== targetItem.p_id) {
console.log("只能在同级之间进行拖拽排序");
// 更新为拖拽前的数据
this.$set(this, "tableData", []);
this.$nextTick(() => {
this.$set(this, "tableData", copyTableHeadData);
this.$set(this, "rowKeys", copyRowKeys);
this.rowDrop();
});
} else {
let length = findChildLen(newTable, sourceItem.id, 0); // 获取拖拽行的子集
const sourceList = newTable.splice(oldIndex, length + 1); //提取拖拽行以及其子集
newTable.splice(newIndex, 0, ...sourceList); //插入到指定位置
let tree = arrayToTree(newTable); // 一维转多维
// 更新数据
this.$set(this, "tableData", []);
this.$nextTick(() => {
this.$set(this, "tableData", tree);
this.$set(this, "rowKeys", copyRowKeys);
this.rowDrop();
});
}
}
复制代码
使用
定义好表头数据,将表头数据和表格数据传给dynamicTable组件,若要打开列设置弹窗,只需调用dynamicTable组件的handleSettingColumn方法
完整项目
目录结构
代码
主组件index.vue
<script>
import ColumnSetting from "./ColumnSetting";
// import { fetchFieldsByUser, saveUserFields } from "./api";
import {
treeToArray,
arrayToTree,
createId,
deepClone,
removeId,
} from "./utils";
// const { moduleKey } = require("@/settings");
export default {
name: "DynamicTable",
props: {
cols: {
type: Array,
default: () => [],
},
tabelflag: {
type: String,
required: true,
},
},
data() {
return {
tableHeadData: [],
columnInfo: []
};
},
components: { ColumnSetting },
created() {
this.tableHeadData = deepClone(this.cols);
},
mounted() {
this.getHeadDataByData();
},
computed: {
columns() {
return this.getShowColumn(this.tableHeadData);
},
},
methods: {
// 过滤不显示列
getShowColumn(arr) {
return arr.filter((col) => !col.hide);
},
// 渲染列
renderCol(arr) {
return arr.map((col) => {
const cols = this.getShowColumn(col.children || []); //过滤掉不显示的列
if (col.render) return col.render(this.$createElement);
if (cols.length == 0) {
return <el-table-column props={col}/>;
}
return (
<el-table-column props={col}>{this.renderCol(cols)}</el-table-column>
);
});
},
// 打开列设置弹窗
handleSettingColumn() {
this.columnInfo = this.$refs.table.$children[0].columns
console.log(this.columnInfo)
this.$refs.csRef.dialogVisible = true;
},
// 从服务器获取表头数据
getHeadDataByData() {
let para = {
pageCode: `${moduleKey}_${this.tabelflag}`,
};
fetchFieldsByUser(para).then((res) => {
const data = res.data || {};
const columns = data.columns || "[]";
this.mergeHeadData(JSON.parse(columns));
});
},
// 本地表头数据和服务器存储数据合并
mergeHeadData(uiData) {
let tableHeadData = createId(deepClone(this.tableHeadData));
// 添加索引,用于排序
tableHeadData = createIndex(tableHeadData);
uiData = createIndex(uiData);
// 多维转一维
let uiData_temp = treeToArray(uiData);
let tableHeadData_temp = treeToArray(tableHeadData);
// 以本地数据为准,合并数据
uiData_temp.forEach((item) => {
tableHeadData_temp.forEach((i) => {
if (item.u_id == i.u_id) {
Object.assign(i, item);
return;
}
});
});
// 根据索引排序
tableHeadData_temp = tableHeadData_temp.sort((a, b) => {
let idx1 = a.idx;
let idx2 = b.idx;
if (idx1 < idx2) {
return -1;
} else if (idx1 > idx2) {
return 1;
} else {
return 0;
}
});
this.$set(this, "tableHeadData", []);
this.$nextTick(() => {
this.$set(
this,
"tableHeadData",
arrayToTree(deepClone(tableHeadData_temp))
);
// 解决设置fixed样式错乱问题
this.$refs.table.doLayout()
});
function createIndex(arr) {
arr.forEach((item, index) => {
item.idx = index;
if (item.children && item.children.length) {
createIndex(item.children);
}
});
return arr;
}
},
// 改变列宽
headDragend(newWidth, oldWidth, column) {
let findCol = findItem(column.property, this.tableHeadData);
if (findCol) findCol.width = newWidth + "";
this.submitTableHeadData(this.tableHeadData);
function findItem(prop, arr) {
for (let item of arr) {
if (item.prop == prop) return item;
if (item.children && item.children.length) {
let _item = findItem(prop, item.children);
if (_item) return _item;
}
}
}
},
// 提交表头数据
submitTableHeadData(data) {
let tempData = removeId(data);
let para = {
pageCode: `${moduleKey}_${this.tabelflag}`,
columns: JSON.stringify(tempData),
};
saveUserFields(para).then((res) => {
console.log("保存表头信息成功");
});
},
handleColumnChange(data) {
this.$set(this, "tableHeadData", []);
this.$nextTick(() => {
this.$set(this, "tableHeadData", data);
this.submitTableHeadData(data);
});
},
},
render() {
return (
<div class="dt-container">
<div class="dt-container-box">
<el-table
ref="table"
props={this.$attrs}
on-header-dragend={this.headDragend}
>
{this.renderCol(this.columns)}
</el-table>
</div>
<ColumnSetting
ref="csRef"
defaultTableHeadData={this.cols}
tableHeadData={this.tableHeadData}
columns={this.columnInfo}
onChangeColumn={this.handleColumnChange}
/>
</div>
);
},
};
</script>
<style scoped>
.dt-container {
width: 100%;
flex: 1;
position: relative;
}
.dt-container-box {
height: 100%;
width: 100%;
display: flex;
position: absolute;
}
</style>
复制代码
列设置弹窗组件columnSetting
<template>
<el-dialog top="5vh" title="列设置" :visible.sync="dialogVisible">
<div class="column-box">
<div class="columnBtn">
<el-button @click="initTableData(defaultTableHeadData)"
>恢复默认</el-button
>
<el-button @click="setColumnShow(tableData, !columnShow)">{{
columnShow ? "全部隐藏" : "全部显示"
}}</el-button>
</div>
<el-table
ref="table"
height="100%"
class="columnTable"
row-key="id"
:data="tableData"
:expand-row-keys="rowKeys"
:tree-props="{ children: 'children' }"
border
stripe
@expand-change="handleExpandChange"
>
<el-table-column type="index" align="center" />
<el-table-column label="列名" prop="label" />
<el-table-column
label="固定列"
prop="fixed"
align="center"
width="160"
>
<template v-if="!row.p_id" slot-scope="{ row }">
<el-select
v-model="row.fixed"
@change="changeFixed(row)"
>
<el-option
v-for="option in fixedOptions"
:key="option.value"
:value="option.value"
:label="option.label"
/>
</el-select>
</template>
</el-table-column>
<el-table-column
label="对齐方式"
prop="align"
align="center"
width="160"
>
<template v-if="!row.children" slot-scope="{ row }">
<el-select v-model="row.align">
<el-option
v-for="option in alignOptions"
:key="option.value"
:value="option.value"
:label="option.label"
/>
</el-select>
</template>
</el-table-column>
<el-table-column label="显示列" prop="show" align="center" width="100">
<template slot-scope="{ row }">
<el-switch v-model="row.show" @change="changeShow(row)"/>
</template>
</el-table-column>
</el-table>
</div>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="changeColumn">确定</el-button>
</template>
</el-dialog>
</template>
<script>
import Sortable from "sortablejs";
import {
treeToArray,
arrayToTree,
deepClone,
createId,
findChildLen,
} from "../utils";
export default {
name: "ColumnSetting",
props: {
tableHeadData: {
type: Array,
default: [],
},
defaultTableHeadData: {
type: Array,
default: [],
},
columns: {
type: Array,
default: []
}
},
data() {
return {
dialogVisible: false,
tableData: [],
fixedOptions: [
{
value: "left",
label: "固定左侧",
},
{
value: "right",
label: "固定右侧",
},
{
value: false,
label: "不固定",
},
],
alignOptions: [
{
value: "left",
label: "左对齐",
},
{
value: "right",
label: "右对齐",
},
{
value: "center",
label: "居中",
},
],
rowKeys: [],
};
},
computed: {
columnShow() {
let tempArr = treeToArray(deepClone(this.tableData));
let show = true;
for (let temp of tempArr) {
if (!temp.show) {
show = false;
break;
}
}
return show;
},
},
methods: {
getEL() {
return this.$refs.table.$el;
},
// 保存展开行,解决数据刷新时,行全部收缩问题
handleExpandChange(row, expanded) {
if (expanded) {
this.rowKeys.push(row.id);
} else {
let index = this.rowKeys.indexOf(row.id);
this.rowKeys.splice(index, 1);
}
},
// 设置全部显示/隐藏
setColumnShow(arr, show) {
arr.forEach((item) => {
item.show = show;
item.hide = !show
if (item.children && item.children) {
this.setColumnShow(item.children, show);
}
});
},
changeFixed(row){
setFixed(row)
let tempArr = treeToArray(deepClone([row]))
let childrens = []
for(let temp of tempArr){
for(let c of this.columns){
if(c.property && c.property == temp.prop){
childrens.push(c)
break
}
}
}
if(childrens.length){
row.width = childrens.reduce((sum, child) => sum + Number(child.realWidth || child.width), 0)
}
function setFixed(obj){
if(!obj.children || !obj.children.length) return
obj.children.forEach(item => {
item.fixed = obj.fixed
setFixed(item)
})
}
},
changeShow(row){
row.hide = !row.hide
},
changeColumn() {
this.$emit("changeColumn", this.tableData);
this.dialogVisible = false;
},
// 初始化数据
initTableData(source) {
let tempArr = createShow(source)
this.$set(this, "tableData", []);
this.$nextTick(() => {
this.$set(this, "tableData", createId(deepClone(tempArr)));
this.rowDrop();
});
function createShow(arr){
arr.forEach(item => {
item.hide ? item.show = false : item.show = true
if(item.children && item.children.length){
createShow(item.children)
}
})
return arr
}
},
// 行拖拽操作
rowDrop() {
const tbody = document.querySelector(
".columnTable .el-table__body-wrapper tbody"
);
let copyTableHeadData = null;
let copyRowKeys = null;
this.sortable = Sortable.create(tbody, {
onStart: () => {
copyTableHeadData = deepClone(this.tableData);
copyRowKeys = deepClone(this.rowKeys);
},
onEnd: ({ newIndex, oldIndex }) => {
let table = Object.assign([], this.tableData);
let newTable = treeToArray(table); //多维转一维
const sourceItem = newTable[oldIndex];
const targetItem = newTable[newIndex];
//判断拖拽是否在同级中操作
if (sourceItem.p_id !== targetItem.p_id) {
console.log("只能在同级之间进行拖拽排序");
// 更新为拖拽前的数据
this.$set(this, "tableData", []);
this.$nextTick(() => {
this.$set(this, "tableData", copyTableHeadData);
this.$set(this, "rowKeys", copyRowKeys);
this.rowDrop();
});
} else {
let length = findChildLen(newTable, sourceItem.id, 0); // 获取拖拽行的子集
const sourceList = newTable.splice(oldIndex, length + 1); //提取拖拽行以及其子集
newTable.splice(newIndex, 0, ...sourceList); //插入到指定位置
let tree = arrayToTree(newTable); // 一维转多维
// 更新数据
this.$set(this, "tableData", []);
this.$nextTick(() => {
this.$set(this, "tableData", tree);
this.$set(this, "rowKeys", copyRowKeys);
this.rowDrop();
});
}
},
});
},
},
watch: {
dialogVisible(value) {
if (value) {
this.initTableData(this.tableHeadData);
}
},
},
};
</script>
<style scoped>
.columnBtn {
text-align: right;
margin-bottom: 10px;
}
::v-deep.columnTable .el-table__placeholder {
display: inline !important;
}
.column-box {
height: 70vh;
overflow: auto;
display: flex;
flex-direction: column;
}
</style>
复制代码
公共方法utils
export function treeToArray(arr){
return arr.reduce((acc, cur) => {
if(Array.isArray(cur.children)){
const copyCur = { ...cur }
delete copyCur.children
return acc.concat(copyCur, treeToArray(cur.children))
}else{
return acc.concat(cur)
}
}, [])
}
export function arrayToTree(arr) {
let temp = {}
let tree = {}
arr.forEach(item => {
temp[item.id] = item
})
let tempKeys = Object.keys(temp)
tempKeys.forEach(key => {
let item = temp[key]
let pid = item.p_id
let pItem = temp[pid]
if(pItem){
if(!pItem.children){
pItem.children = []
}
pItem.children.push(item)
}else{
tree[item.id] = item
}
})
return Object.keys(tree).map(key => tree[key])
}
export function deepClone(obj) {
let newObj = null
if (typeof obj === 'object' && obj !== null) {
newObj = obj instanceof Array ? [] : {}
for (let i in obj) {
newObj[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i]
}
} else {
newObj = obj
}
return newObj
}
export function createId(arr, defaultId = '_'){
arr.forEach((item, index) => {
item.id = defaultId + index
if(defaultId != '_') item.p_id = defaultId
if(item.children && item.children.length) createId(item.children, item.id)
})
return arr
}
export function removeId(arr){
arr.forEach(item => {
item.id && delete item.id
item.p_id && delete item.p_id
if(item.children && item.children.length) removeId(item.children)
})
return arr
}
export function findChildLen(arr, id, dLen){
handler(id)
function handler(id){
let temp = []
arr.forEach(item => {
if(item.p_id == id){
dLen++
temp.push(item)
}
})
temp.forEach(item => {
handler(item.id)
})
}
return dLen
}
复制代码
请求方法api
import axios from 'axios'
export const fetchFieldsByUser = (data) => axios.post('获取表头数据接口', data)
export const saveUserFields = (data) => axios.post('保存表头数据接口', data)
复制代码
调用示例
<template>
<div id="app">
<el-button @click="handleSettingColumn">列设置</el-button>
<div style="height: 500px;display: flex;">
<DynamicTable
ref="DTable" :cols="cols"
:tabelflag="$options.name" :data="rows"
border
/>
</div>
</div>
</template>
<script>
import DynamicTable from '@/components/DynamicTable'
export default {
name: 'App',
components: { DynamicTable },
data(){
return {
cols: [{
u_id: '0',
label: '日期',
prop: 'date',
render(h){
return h('el-table-column', {
props: {
...this
},
scopedSlots: {
default: (props) => {
const { row } = props
return <span><i class="el-icon-date"/>{row.date}</span>
}
}
})
}
}, {
u_id: '1',
label: '配送信息',
children: [{
u_id: '10',
label: '姓名',
prop: 'name',
width: '120'
}, {
u_id: '11',
label: '地址',
children: [{
u_id: '110',
label: '省份',
prop: 'province',
width: '120'
}, {
u_id: '111',
label: '市区',
prop: 'city',
width: '120'
}, {
u_id: '112',
label: '地址',
prop: 'address',
width: '300'
}, {
u_id: '113',
label: '邮编',
prop: 'zip',
width: '120'
}]
}]
}],
rows: [{
date: '2016-05-03',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333
}, {
date: '2016-05-02',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333
}, {
date: '2016-05-04',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333
}, {
date: '2016-05-01',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333
}, {
date: '2016-05-08',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333
}, {
date: '2016-05-06',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333
}, {
date: '2016-05-07',
name: '王小虎',
province: '上海',
city: '普陀区',
address: '上海市普陀区金沙江路 1518 弄',
zip: 200333
}]
}
},
methods: {
handleSettingColumn(){
this.$refs.DTable.handleSettingColumn()
}
}
}
</script>
复制代码