perf[Tree-Table]: organize the structure and add documentation (#1673)

This commit is contained in:
花裤衩 2019-03-07 14:13:36 +08:00 committed by GitHub
parent dc6030bce6
commit 5ca6f79836
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 365 additions and 201 deletions

View File

@ -0,0 +1,220 @@
- [Enlgish](#Brief)
# 中文
## 写在前面
此组件仅提供一个创建 `TreeTable` 的解决思路。它基于`element-ui`的 table 组件实现,通过`el-table`的`row-style`方法,在里面判断元素是否需要隐藏或者显示,从而实现`TreeTable`的展开与收起。
并且本组件充分利用 `vue` 插槽的特性来方便用户自定义。
`evel.js` 里面,`addAttrs` 方法会给数据添加几个属性,`treeTotable` 会对数组扁平化。这些操作都不会破坏源数据,只是会新增属性。
## Props 说明
| Attribute | Description | Type | Default |
| :--------------: | :--------------------------------- | :-----: | :------: |
| data | 原始展示数据 | Array | [] |
| columns | 列属性 | Array | [] |
| defaultExpandAll | 默认是否全部展开 | Boolean | false |
| defaultChildren | 指定子树为节点对象的某个属性值 | String | children | |
| indent | 相邻级节点间的水平缩进,单位为像素 | Number | 50 |
> 任何 `el-table` 的属性都支持,例如`border`、`fit`、`size`或者`@select`、`@cell-click`等方法。详情属性见`el-table`文档。
---
### 代码示例
```html
<tree-table :data="data" :columns="columns" border>
```
#### data(**必填**)
```js
const data = [
{
name:'1'
children: [
{
name: '1-1'
},
{
name: '1-2'
}
]
},
{
name: `2`
}
]
```
#### columns(**必填**)
- label: 显示在表头的文字
- key: 对应 data 的 key。treeTable 将显示相应的 value
- expand: `true` or `false`。若为 true则在该列显示展开收起图标
- checkbox: `true` or `false`。若为 true则在该列显示`checkbox`
- width: 每列的宽度,为一个数字(可选)。例如`200`
- align: 对齐方式 `left/center/right`
- header-align: 表头对齐方式 `left/center/right`
```javascript
const columns = [
{
label: 'Checkbox',
checkbox: true
},
{
label: '',
key: 'id',
expand: true
},
{
label: 'Event',
key: 'event',
width: 200,
align: 'left'
},
{
label: 'Scope',
key: 'scope'
}
]
```
> 树表组件将会根据 columns 的 key 属性生成具名插槽,如果你需要对列数据进行自定义,通过插槽即可实现
```html
<template slot="your key" slot-scope="{scope}">
<el-tag>level: {{ scope.row._level }}</el-tag>
<el-tag>expand: {{ scope.row._expand }}</el-tag>
<el-tag>select: {{ scope.row._select }}</el-tag>
</template>
```
## Events
目前提供了几个方法,不过只是`beta`版本,之后很可能会修改。
```js
this.$refs.TreeTable.addChild(row, data) //添加子元素
this.$refs.TreeTable.addBrother(row, data) //添加兄弟元素
this.$refs.TreeTable.delete(row) //删除该元素
```
## 其他
如果有其他的需求,请参考[el-table](http://element-cn.eleme.io/#/en-US/component/table)的 api 自行修改 index.vue
# English
## Brief
This component only provides a solution for creating `TreeTable`. It is based on the `element-ui` table component. It uses the `row-style` method of `el-table` to determine whether the element needs to be hidden or displayed.
And this component makes full use of the features of the `vue` slot to make it user-friendly.
In `evel.js`, the `addAttrs` method adds several properties to the data, and `treeTotable` flattens the array. None of these operations will destroy the source data, just add properties.
## Props
| Attribute | Description | Type | Default |
| :--------------: | :----------------------------------------------------------- | :-----: | :------: |
| data | original display data | Array | [] |
| columns | column attribute | Array | [] |
| defaultExpandAll | whether to expand all nodes by default | Boolean | false |
| defaultChildren | specify which node object is used as the node's subtree | String | children | |
| indent | horizontal indentation of nodes in adjacent levels in pixels | Number | 50 |
> Any of the `el-table` properties are supported, such as `border`, `fit`, `size` or `@select`, `@cell-click`. See the ʻel-table` documentation for details.
---
### Example
```html
<tree-table :data="data" :columns="columns" border>
```
#### data(**Required**)
```js
const data = [
{
name:'1'
children: [
{
name: '1-1'
},
{
name: '1-2'
}
]
},
{
name: `2`
}
]
```
#### columns(**Required**)
- label: text displayed in the header
- key: data.key will show in column
- expand: `true` or `false`
- checkbox: `true` or `false`
- width: column width 。such as `200`
- align: alignment `left/center/right`
- header-align: alignment of the table header `left/center/right`
```javascript
const columns = [
{
label: 'Checkbox',
checkbox: true
},
{
label: '',
key: 'id',
expand: true
},
{
label: 'Event',
key: 'event',
width: 200,
align: 'left'
},
{
label: 'Scope',
key: 'scope'
}
]
```
> The tree table component will generate a named slot based on the key property of columns. If you need to customize the column data, you can do it through the slot.
```html
<template slot="your key" slot-scope="{scope}">
<el-tag>level: {{ scope.row._level }}</el-tag>
<el-tag>expand: {{ scope.row._expand }}</el-tag>
<el-tag>select: {{ scope.row._select }}</el-tag>
</template>
```
## Events
Several methods are currently available, but only the `beta` version, which is likely to be modified later.
```js
this.$refs.TreeTable.addChild(row, data) //Add child elements
this.$refs.TreeTable.addBrother(row, data) //Add a sibling element
this.$refs.TreeTable.delete(row) //Delete the element
```
## Other
If you have other requirements, please refer to the [el-table](http://element-cn.eleme.io/#/en-US/component/table) api to modify the index.vue

View File

@ -1,99 +0,0 @@
## 写在前面
此组件仅提供一个创建 TreeTable 的解决思路,本组件充分利用 vue 插槽的特性,方便用户自定义
evel.js 里面 `addAttrs` 方法会给数据添加几个属性treeTotable 会对数组扁平化。这些操作都不会破坏源数据,只是会新增属性。
调用 addAttrs 后,因\_\_parent 属性,会造成数据循环引用,使用 JSON.stringify()报错,所以转成 JSON 之前需要清除\_\_parent 属性。
## prop 说明
- data原始数据要求是一个数组或者对象
- columns列属性,要求是一个数组)
- renderContent数组扁平化方法可选
- defaultExpandAll默认是否全部展开默认全部展开
- defaultChildren子元素名默认为 children
- spreadOffset扩展符号的偏移量默认为 50px
- checkboxOffset复选框的偏移量默认为 50px
---
### 代码示例
- data(**必填**)
原始数据,
```js
const data = [
{
key1: value1,
key2: value2,
children: [
{
key1: value1
},
{
key1: value1
}
]
},
{
key1: value1
}
]
```
或者
```javascript
{
key1: value1,
key2: value2,
children: [{
key1: value1
},
{
key1: value1
}]
}
```
- columns
1. label: 显示在表头的文字
2. key: 对应 data 的 key。treeTable 将显示相应的 value
3. width: 每列的宽度,为一个数字(可选)
树表组件将会根据 columns 的 key 属性生成具名插槽,如果你需要对列数据进行自定义,通过插槽即可实现
```javascript
const columns = [
// 建议第一列做展开收缩操作
{ label: '', key: '__spread', width: '200' },
// 如果添加复选框
{ label: '', key: '__checkbox', width: '200' },
{
label: string,
key: string,
width: number
},
{
label: string,
key: string,
width: number
}
]
```
#### renderContent
解析函数function非必须
如果不提供,将使用默认的[evalFunc](./eval.js)
如果提供了 evalFunc,那么会用提供的 evalFunc 去解析 data并返回 treeTable 渲染所需要的值。
## 其他
如果有其他的需求,请参考[el-table](http://element-cn.eleme.io/#/en-US/component/table)的 api 自行修改 index.vue

View File

@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M44.8 0h79.543C126.78 0 128 1.422 128 4.267v23.466c0 2.845-1.219 4.267-3.657 4.267H44.8c-2.438 0-3.657-1.422-3.657-4.267V4.267C41.143 1.422 42.362 0 44.8 0zm22.857 48h56.686c2.438 0 3.657 1.422 3.657 4.267v23.466c0 2.845-1.219 4.267-3.657 4.267H67.657C65.22 80 64 78.578 64 75.733V52.267C64 49.422 65.219 48 67.657 48zm0 48h56.686c2.438 0 3.657 1.422 3.657 4.267v23.466c0 2.845-1.219 4.267-3.657 4.267H67.657C65.22 128 64 126.578 64 123.733v-23.466C64 97.422 65.219 96 67.657 96zM50.286 68.267c2.02 0 3.657-1.91 3.657-4.267 0-2.356-1.638-4.267-3.657-4.267H17.37V32h6.4c2.02 0 3.658-1.91 3.658-4.267V4.267C27.429 1.91 25.79 0 23.77 0H3.657C1.637 0 0 1.91 0 4.267v23.466C0 30.09 1.637 32 3.657 32h6.4v80c0 2.356 1.638 4.267 3.657 4.267h36.572c2.02 0 3.657-1.91 3.657-4.267 0-2.356-1.638-4.267-3.657-4.267H17.37V68.267h32.915z"/></svg>

After

Width:  |  Height:  |  Size: 906 B

View File

@ -10,6 +10,7 @@ import Layout from '@/views/layout/Layout'
import componentsRouter from './modules/components' import componentsRouter from './modules/components'
import chartsRouter from './modules/charts' import chartsRouter from './modules/charts'
import tableRouter from './modules/table' import tableRouter from './modules/table'
import treeTableRouter from './modules/tree-table'
import nestedRouter from './modules/nested' import nestedRouter from './modules/nested'
/** note: sub-menu only appear when children.length>=1 /** note: sub-menu only appear when children.length>=1
@ -162,6 +163,7 @@ export const asyncRouterMap = [
chartsRouter, chartsRouter,
nestedRouter, nestedRouter,
tableRouter, tableRouter,
treeTableRouter,
{ {
path: '/example', path: '/example',

View File

@ -30,18 +30,6 @@ const tableRouter = {
name: 'InlineEditTable', name: 'InlineEditTable',
meta: { title: 'inlineEditTable' } meta: { title: 'inlineEditTable' }
}, },
{
path: 'tree-table',
component: () => import('@/views/table/treeTable/treeTable'),
name: 'TreeTableDemo',
meta: { title: 'treeTable' }
},
{
path: 'custom-tree-table',
component: () => import('@/views/table/treeTable/customTreeTable'),
name: 'CustomTreeTableDemo',
meta: { title: 'customTreeTable' }
},
{ {
path: 'complex-table', path: 'complex-table',
component: () => import('@/views/table/complexTable'), component: () => import('@/views/table/complexTable'),

View File

@ -0,0 +1,29 @@
/** When your routing table is too long, you can split it into small modules**/
import Layout from '@/views/layout/Layout'
const treeTableRouter = {
path: '/tree-table',
component: Layout,
redirect: '/table/complex-table',
name: 'TreeTable',
meta: {
title: 'treeTable',
icon: 'tree-table'
},
children: [
{
path: 'index',
component: () => import('@/views/tree-table/index'),
name: 'TreeTableDemo',
meta: { title: 'treeTable' }
},
{
path: 'custom',
component: () => import('@/views/tree-table/custom'),
name: 'CustomTreeTableDemo',
meta: { title: 'customTreeTable' }
}
]
}
export default treeTableRouter

View File

@ -1,4 +1,4 @@
export const data = [ const data = [
{ {
name: '1', name: '1',
timeLine: 100, timeLine: 100,
@ -47,3 +47,5 @@ export const data = [
} }
] ]
export default data

View File

@ -1,12 +1,10 @@
<template> <template>
<div> <div>
<div class="app-container"> <div class="app-container">
<el-tag style="margin-bottom:20px;">
<a <el-button type="primary" size="small" style="margin:0 0 20px 0;">
href="https://github.com/PanJiaChen/vue-element-admin/tree/master/src/components/TreeTable" <a href="https://github.com/PanJiaChen/vue-element-admin/tree/master/src/components/TreeTable" target="_blank">Documentation</a>
target="_blank" </el-button>
>Documentation</a>
</el-tag>
<tree-table <tree-table
ref="TreeTable" ref="TreeTable"
@ -85,9 +83,8 @@
</template> </template>
<script> <script>
import TreeTable from '@/components/TreeTable' import TreeTable from '@/components/TreeTable'
import { data } from './data.js' import data from './data.js'
export default { export default {
components: { TreeTable }, components: { TreeTable },
@ -145,11 +142,11 @@ export default {
}, },
addMenuItem(row, type) { addMenuItem(row, type) {
if (type === 'children') { if (type === 'children') {
this.$refs.TreeTable.addChild(row, { name: 'child' }) this.$refs.TreeTable.addChild(row, { name: 'child', timeLine: this.randomNum() })
} }
if (type === 'brother') { if (type === 'brother') {
this.$refs.TreeTable.addBrother(row, { name: 'brother' }) this.$refs.TreeTable.addBrother(row, { name: 'brother', timeLine: this.randomNum() })
} }
}, },
deleteItem(row) { deleteItem(row) {
@ -157,6 +154,12 @@ export default {
}, },
selectChange(val) { selectChange(val) {
console.log(val) console.log(val)
},
randomNum() {
// return 1~100
const max = 100
const min = 1
return Math.floor(Math.random() * (max - min + 1) + min)
} }
} }
} }

View File

@ -0,0 +1,80 @@
const data = [
{
id: 0,
event: 'Event-0',
timeLine: 50
},
{
id: 1,
event: 'Event-1',
timeLine: 100,
children: [
{
id: 2,
event: 'Event-2',
timeLine: 10
},
{
id: 3,
event: 'Event-3',
timeLine: 90,
children: [
{
id: 4,
event: 'Event-4',
timeLine: 5
},
{
id: 5,
event: 'Event-5',
timeLine: 10
},
{
id: 6,
event: 'Event-6',
timeLine: 75,
children: [
{
id: 7,
event: 'Event-7',
timeLine: 50,
children: [
{
id: 71,
event: 'Event-7-1',
timeLine: 25
},
{
id: 72,
event: 'Event-7-2',
timeLine: 5
},
{
id: 73,
event: 'Event-7-3',
timeLine: 20
}
]
},
{
id: 8,
event: 'Event-8',
timeLine: 25
}
]
}
]
}
]
}
]
export default data

View File

@ -3,7 +3,7 @@
<div style="margin-bottom:20px;"> <div style="margin-bottom:20px;">
<el-button type="primary" class="option-item"> <el-button type="primary" size="small" class="option-item">
<a href="https://github.com/PanJiaChen/vue-element-admin/tree/master/src/components/TreeTable" target="_blank">Documentation</a> <a href="https://github.com/PanJiaChen/vue-element-admin/tree/master/src/components/TreeTable" target="_blank">Documentation</a>
</el-button> </el-button>
@ -42,8 +42,8 @@
</template> </template>
<script> <script>
import treeTable from '@/components/TreeTable' import treeTable from '@/components/TreeTable'
import data from './data'
export default { export default {
name: 'TreeTableDemo', name: 'TreeTableDemo',
@ -78,83 +78,7 @@ export default {
key: 'operation' key: 'operation'
} }
], ],
data: [ data: data
{
id: 0,
event: 'Event-0',
timeLine: 50
},
{
id: 1,
event: 'Event-1',
timeLine: 100,
children: [
{
id: 2,
event: 'Event-2',
timeLine: 10
},
{
id: 3,
event: 'Event-3',
timeLine: 90,
children: [
{
id: 4,
event: 'Event-4',
timeLine: 5
},
{
id: 5,
event: 'Event-5',
timeLine: 10
},
{
id: 6,
event: 'Event-6',
timeLine: 75,
children: [
{
id: 7,
event: 'Event-7',
timeLine: 50,
children: [
{
id: 71,
event: 'Event-7-1',
timeLine: 25
},
{
id: 72,
event: 'Event-7-2',
timeLine: 5
},
{
id: 73,
event: 'Event-7-3',
timeLine: 20
}
]
},
{
id: 8,
event: 'Event-8',
timeLine: 25
}
]
}
]
}
]
}
]
} }
}, },
watch: { watch: {
@ -176,6 +100,20 @@ export default {
}, },
click(scope) { click(scope) {
console.log(scope) console.log(scope)
const row = scope.row
const message = Object.keys(row)
.map(i => {
return `<p>${i}: ${row[i]}</p>`
})
.join('')
this.$notify({
title: 'Success',
dangerouslyUseHTMLString: true,
message: message,
type: 'success'
})
} }
} }
} }