forked from PanJiaChen/vue-element-admin
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
perf[Tree-Table]: refactor tree-table (PanJiaChen#1587)
- Loading branch information
1 parent
fc9e724
commit dc6030b
Showing
8 changed files
with
558 additions
and
393 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,48 @@ | ||
/** | ||
* @Author: jianglei | ||
* @Date: 2017-10-12 12:06:49 | ||
*/ | ||
'use strict' | ||
import Vue from 'vue' | ||
export default function treeToArray(data, expandAll, parent = null, level = null) { | ||
|
||
// Flattened array | ||
export default function treeToArray(data, children = 'children') { | ||
let tmp = [] | ||
Array.from(data).forEach(function(record) { | ||
if (record._expanded === undefined) { | ||
Vue.set(record, '_expanded', expandAll) | ||
data.forEach((item, index) => { | ||
Vue.set(item, '_index', index) | ||
tmp.push(item) | ||
if (item[children] && item[children].length > 0) { | ||
const res = treeToArray(item[children], children) | ||
tmp = tmp.concat(res) | ||
} | ||
let _level = 1 | ||
if (level !== undefined && level !== null) { | ||
_level = level + 1 | ||
} | ||
Vue.set(record, '_level', _level) | ||
// 如果有父元素 | ||
if (parent) { | ||
Vue.set(record, 'parent', parent) | ||
}) | ||
return tmp | ||
} | ||
|
||
export function addAttrs(data, { parent = null, preIndex = false, level = 0, expand = false, children = 'children', show = true, select = false } = {}) { | ||
data.forEach((item, index) => { | ||
const _id = (preIndex ? `${preIndex}-${index}` : index) + '' | ||
Vue.set(item, '_id', _id) | ||
Vue.set(item, '_level', level) | ||
Vue.set(item, '_expand', expand) | ||
Vue.set(item, '_parent', parent) | ||
Vue.set(item, '_show', show) | ||
Vue.set(item, '_select', select) | ||
if (item[children] && item[children].length > 0) { | ||
addAttrs(item[children], { | ||
parent: item, | ||
level: level + 1, | ||
expand, | ||
preIndex: _id, | ||
children, | ||
status, | ||
select | ||
}) | ||
} | ||
tmp.push(record) | ||
if (record.children && record.children.length > 0) { | ||
const children = treeToArray(record.children, expandAll, record, _level) | ||
tmp = tmp.concat(children) | ||
}) | ||
} | ||
|
||
export function cleanParentAttr(data, children = 'children') { | ||
data.forEach(item => { | ||
item._parent = null | ||
if (item[children] && item[children].length > 0) { | ||
addAttrs(item[children], children) | ||
} | ||
}) | ||
return tmp | ||
return data | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,127 +1,177 @@ | ||
<template> | ||
<el-table :data="formatData" :row-style="showRow" v-bind="$attrs"> | ||
<el-table-column v-if="columns.length===0" width="150"> | ||
<el-table :data="tableData" :row-style="showRow" v-bind="$attrs" v-on="$listeners" > | ||
<slot name="selection" /> | ||
<slot name="pre-column" /> | ||
<el-table-column | ||
v-for="item in columns" | ||
:label="item.label" | ||
:key="item.key" | ||
:width="item.width" | ||
:align="item.align||'center'" | ||
:header-align="item.headerAlign"> | ||
<template slot-scope="scope"> | ||
<span v-for="space in scope.row._level" :key="space" class="ms-tree-space"/> | ||
<span v-if="iconShow(0,scope.row)" class="tree-ctrl" @click="toggleExpanded(scope.$index)"> | ||
<i v-if="!scope.row._expanded" class="el-icon-plus"/> | ||
<i v-else class="el-icon-minus"/> | ||
</span> | ||
{{ scope.$index }} | ||
<slot :scope="scope" :name="item.key"> | ||
<template v-if="item.expand"> | ||
<span :style="{'padding-left':+scope.row._level*indent + 'px'} "/> | ||
<span v-show="showSperadIcon(scope.row)" class="tree-ctrl" @click="toggleExpanded(scope.$index)"> | ||
<i v-if="!scope.row._expand" class="el-icon-plus" /> | ||
<i v-else class="el-icon-minus" /> | ||
</span> | ||
</template> | ||
<template v-if="item.checkbox"> | ||
<el-checkbox | ||
v-if="scope.row[defaultChildren]&&scope.row[defaultChildren].length>0" | ||
:style="{'padding-left':+scope.row._level*indent + 'px'} " | ||
:indeterminate="scope.row._select" | ||
v-model="scope.row._select" | ||
@change="handleCheckAllChange(scope.row)" /> | ||
<el-checkbox | ||
v-else | ||
:style="{'padding-left':+scope.row._level*indent + 'px'} " | ||
v-model="scope.row._select" | ||
@change="handleCheckAllChange(scope.row)" /> | ||
</template> | ||
{{ scope.row[item.key] }} | ||
</slot> | ||
</template> | ||
</el-table-column> | ||
<el-table-column v-for="(column, index) in columns" v-else :key="column.value" :label="column.text" :width="column.width"> | ||
<template slot-scope="scope"> | ||
<!-- Todo --> | ||
<!-- eslint-disable-next-line vue/no-confusing-v-for-v-if --> | ||
<span v-for="space in scope.row._level" v-if="index === 0" :key="space" class="ms-tree-space"/> | ||
<span v-if="iconShow(index,scope.row)" class="tree-ctrl" @click="toggleExpanded(scope.$index)"> | ||
<i v-if="!scope.row._expanded" class="el-icon-plus"/> | ||
<i v-else class="el-icon-minus"/> | ||
</span> | ||
{{ scope.row[column.value] }} | ||
</template> | ||
</el-table-column> | ||
<slot/> | ||
</el-table> | ||
</template> | ||
|
||
<script> | ||
/** | ||
Auth: Lei.j1ang | ||
Created: 2018/1/19-13:59 | ||
*/ | ||
import treeToArray from './eval' | ||
import treeToArray, { addAttrs } from './eval.js' | ||
export default { | ||
name: 'TreeTable', | ||
props: { | ||
/* eslint-disable */ | ||
data: { | ||
type: [Array, Object], | ||
required: true | ||
type: Array, | ||
required: true, | ||
default: () => [] | ||
}, | ||
columns: { | ||
type: Array, | ||
default: () => [] | ||
}, | ||
evalFunc: Function, | ||
evalArgs: Array, | ||
expandAll: { | ||
defaultExpandAll: { | ||
type: Boolean, | ||
default: false | ||
}, | ||
defaultChildren: { | ||
type: String, | ||
default: 'children' | ||
}, | ||
indent: { | ||
type: Number, | ||
default: 50 | ||
} | ||
}, | ||
data() { | ||
return { | ||
guard: 1 | ||
} | ||
}, | ||
computed: { | ||
// 格式化数据源 | ||
formatData: function() { | ||
let tmp | ||
if (!Array.isArray(this.data)) { | ||
tmp = [this.data] | ||
} else { | ||
tmp = this.data | ||
children() { | ||
return this.defaultChildren | ||
}, | ||
tableData() { | ||
const data = this.data | ||
if (this.data.length === 0) { | ||
return [] | ||
} | ||
const func = this.evalFunc || treeToArray | ||
const args = this.evalArgs ? Array.concat([tmp, this.expandAll], this.evalArgs) : [tmp, this.expandAll] | ||
return func.apply(null, args) | ||
addAttrs(data, { | ||
expand: this.defaultExpandAll, | ||
children: this.defaultChildren | ||
}) | ||
const retval = treeToArray(data, this.defaultChildren) | ||
return retval | ||
} | ||
}, | ||
methods: { | ||
showRow: function(row) { | ||
const show = (row.row.parent ? (row.row.parent._expanded && row.row.parent._show) : true) | ||
row.row._show = show | ||
return show ? 'animation:treeTableShow 1s;-webkit-animation:treeTableShow 1s;' : 'display:none;' | ||
addBrother(row, data) { | ||
if (row._parent) { | ||
row._parent.children.push(data) | ||
} else { | ||
this.data.push(data) | ||
} | ||
}, | ||
// 切换下级是否展开 | ||
toggleExpanded: function(trIndex) { | ||
const record = this.formatData[trIndex] | ||
record._expanded = !record._expanded | ||
addChild(row, data) { | ||
if (!row.children) { | ||
this.$set(row, 'children', []) | ||
} | ||
row.children.push(data) | ||
}, | ||
// 图标显示 | ||
iconShow(index, record) { | ||
return (index === 0 && record.children && record.children.length > 0) | ||
delete(row) { | ||
const { _index, _parent } = row | ||
if (_parent) { | ||
_parent.children.splice(_index, 1) | ||
} else { | ||
this.data.splice(_index, 1) | ||
} | ||
}, | ||
getData() { | ||
return this.tableData | ||
}, | ||
showRow: function({ row }) { | ||
const parent = row._parent | ||
const show = parent ? parent._expand && parent._show : true | ||
row._show = show | ||
return show | ||
? 'animation:treeTableShow 1s;-webkit-animation:treeTableShow 1s;' | ||
: 'display:none;' | ||
}, | ||
showSperadIcon(record) { | ||
return record[this.children] && record[this.children].length > 0 | ||
}, | ||
toggleExpanded(trIndex) { | ||
const record = this.tableData[trIndex] | ||
const expand = !record._expand | ||
record._expand = expand | ||
}, | ||
handleCheckAllChange(row) { | ||
this.selcetRecursion(row, row._select, this.defaultChildren) | ||
this.isIndeterminate = row._select | ||
}, | ||
selcetRecursion(row, select, children = 'children') { | ||
if (select) { | ||
this.$set(row, '_expand', true) | ||
this.$set(row, '_show', true) | ||
} | ||
const sub_item = row[children] | ||
if (sub_item && sub_item.length > 0) { | ||
sub_item.map(child => { | ||
child._select = select | ||
this.selcetRecursion(child, select, children) | ||
}) | ||
} | ||
} | ||
} | ||
} | ||
</script> | ||
<style rel="stylesheet/css"> | ||
@keyframes treeTableShow { | ||
from {opacity: 0;} | ||
to {opacity: 1;} | ||
} | ||
@-webkit-keyframes treeTableShow { | ||
from {opacity: 0;} | ||
to {opacity: 1;} | ||
} | ||
</style> | ||
|
||
<style lang="scss" rel="stylesheet/scss" scoped> | ||
$color-blue: #2196F3; | ||
$space-width: 18px; | ||
.ms-tree-space { | ||
position: relative; | ||
top: 1px; | ||
display: inline-block; | ||
font-style: normal; | ||
font-weight: 400; | ||
line-height: 1; | ||
width: $space-width; | ||
height: 14px; | ||
&::before { | ||
content: "" | ||
} | ||
<style> | ||
@keyframes treeTableShow { | ||
from { | ||
opacity: 0; | ||
} | ||
to { | ||
opacity: 1; | ||
} | ||
.processContainer{ | ||
width: 100%; | ||
height: 100%; | ||
} | ||
@-webkit-keyframes treeTableShow { | ||
from { | ||
opacity: 0; | ||
} | ||
table td { | ||
line-height: 26px; | ||
to { | ||
opacity: 1; | ||
} | ||
} | ||
.tree-ctrl{ | ||
position: relative; | ||
cursor: pointer; | ||
color: $color-blue; | ||
margin-left: -$space-width; | ||
} | ||
.tree-ctrl { | ||
position: relative; | ||
cursor: pointer; | ||
color: #2196f3; | ||
} | ||
</style> |
Oops, something went wrong.