|
1 | | -# vue-new-demo |
| 1 | +# Table-Tree |
| 2 | +基于 element-ui CSS样式设计的 `Table-Tree` 组件。开放访问 `TableStore`方法,自定义扩展,自定义渲染。 |
2 | 3 |
|
3 | | -## Project setup |
4 | | -``` |
5 | | -yarn install |
6 | | -``` |
7 | 4 |
|
8 | | -### Compiles and hot-reloads for development |
9 | | -``` |
10 | | -yarn run serve |
11 | | -``` |
| 5 | +## Feature |
| 6 | +1. 通过 column 每一列自定义 `render` 函数 + `TableStore` 暴露的各种方法来操作 table 的数据源 实现各种功能,解决了 element-ui 一列仅支持特定的几个 type 展示的问题。 |
| 7 | +2. 通过 Vue 实例的 computed 对象属性 tableData 返回 `TableStore.state.data`,解决了*组件数据源更新*导致*组件状态被更新*的问题。 |
| 8 | +3. 支持特定的expand Depth,渲染指定深度的属性接口。 |
12 | 9 |
|
13 | | -### Compiles and minifies for production |
14 | | -``` |
15 | | -yarn run build |
| 10 | + |
| 11 | +## Interfaces |
| 12 | +```ts |
| 13 | +interface ColumnConfig { /* 列配置 */ |
| 14 | + label?: string; |
| 15 | + prop: string; |
| 16 | + key: string | number; |
| 17 | + width: number | string/* % */; |
| 18 | + render(h: Function, param: ColumnParam)?: VNode; /* must return a vnode instance */ |
| 19 | + // filter(h: Function, param: ColumnParam)?: void; /* 暂未实现 */ |
| 20 | + // sortBy(h: Function, param: ColumnParam)?: void; /* 暂未实现 */ |
| 21 | +} |
| 22 | + |
| 23 | +interface ColumnParam { /* 列参数对象 */ |
| 24 | + depth: number; |
| 25 | + expandDepth: number; |
| 26 | + row: RowModel; // 当前数据项 对应后端传入 list 的当前项的 model |
| 27 | + rowIndex: number; |
| 28 | + column: ColumnConfig; |
| 29 | + columnIndex: number; |
| 30 | + store: TableStore; |
| 31 | +} |
| 32 | + |
| 33 | +interface TableStore { |
| 34 | + setState(state: TableState); /* 调用以更改当前 table 内部的状态*/ |
| 35 | + isRowExpanded(row: RowModel): void; /* 判断当前行是否是展开状态 */ |
| 36 | + toggleRowExpansion(row: RowModel, expanded?: boolean); /* 切换当前行展开收起状态 */ |
| 37 | + isRowSelected(row: RowModel); |
| 38 | + toggleRowSelection(row: RowModel, selected?: boolean); |
| 39 | +} |
| 40 | + |
| 41 | +interface TableState { |
| 42 | + data: null | Array<RowModel>; |
| 43 | + columns: Array<ColumnConfig>; |
| 44 | + rowKey: String; |
| 45 | + selectRows: Array<RowModel>; /* 已选中行 */ |
| 46 | + expandRows: Array<RowModel>; /* 已展开行 */ |
| 47 | + defaultExpandAll: boolean; /* 默认是否展开所有 */ |
| 48 | + // filter /* 暂未实现 */ |
| 49 | + // sortBy /* 暂未实现 */ |
| 50 | +} |
| 51 | + |
| 52 | +interface RowModel { |
| 53 | + [rowKey as string]: number | string; |
| 54 | + [prop as string]: any; /* 可传入任意属性任意值的数据 */ |
| 55 | +}; |
16 | 56 | ``` |
17 | 57 |
|
18 | | -### Run your tests |
| 58 | + |
| 59 | +## Usage |
| 60 | +```html |
| 61 | +<TableTreeDepth |
| 62 | + class="tree-table-view" |
| 63 | + :row-key="rowKey" |
| 64 | + :show-header="true" |
| 65 | + :data-source="TableData" |
| 66 | + :columns="columns" |
| 67 | + :expand-depth="1" |
| 68 | + :select-rows="[TableData[0].children[0], TableData[0].children[1]]" |
| 69 | +/> |
19 | 70 | ``` |
20 | | -yarn run test |
| 71 | + |
| 72 | +### Props |
| 73 | +props 大部分与 element-ui 的 table 类似。有几点不同: |
| 74 | + |
| 75 | +#### Columns |
| 76 | +用于映射列表中的数据。 |
| 77 | + |
| 78 | +> 并未使用 TypeScript 编写,仅用以表示类型方便所以使用了 TypeScript 的 interface。 |
| 79 | +
|
| 80 | +- 需手动编写 `columns` `Array<ColumnConfig>`,ColumnConfig 数据结构描述如下: |
| 81 | + |
| 82 | +| 字段名称 | 字段类型 | 必传 | 默认值 | description | |
| 83 | +| --------------------- | :------- | :----- | :---------- | :----- | |
| 84 | +| label | string | true | - | 当前列表头显示内容 | |
| 85 | +| prop | string | true | - | 当前列 server model 字段的 key | |
| 86 | +| key | string | number | - | 当前列 virtual-dom(v-for) 的 key | |
| 87 | +| width | number | false | - | 当前列的宽度 | |
| 88 | +| render | function | false | `row[prop]` | 当前列的自定义 render 函数 => render(h, { depth: Number, expandDepth: Number, row: Row, rowIndex: Number, column: Column, columnIndex: Number, store: TableStore }) | |
| 89 | +| filter **暂未实现** | function | false | - | 当前列的 filter 函数 => filter(...args) | |
| 90 | +| sortBy **暂未实现** | function | false | - | 当前列的 sortBy 函数 => filter(...args) | |
| 91 | + |
| 92 | +##### Columns demo: |
| 93 | +```jsx |
| 94 | +const columns = [{ |
| 95 | + label: '姓名', |
| 96 | + key: 'name', |
| 97 | +}, { |
| 98 | + prop: "_expand", |
| 99 | + key: 0, |
| 100 | + render: (h, { store, row, column, depth }) => { |
| 101 | + if (row.children && row.children.length) { |
| 102 | + const expanded = store.isRowExpanded(row); /* 调用 store.isRowExpanded 方法 */ |
| 103 | + const classname = expanded ? "el-icon-minus" : "el-icon-plus"; |
| 104 | + |
| 105 | + return ( |
| 106 | + <i |
| 107 | + style={`padding-left: ${depth * 20}px`} |
| 108 | + class={classname} |
| 109 | + onClick={() => store.toggleRowExpansion(row)} /* 调用 store.toggleRowExpansion 方法 */ |
| 110 | + /> |
| 111 | + ); |
| 112 | + } else { |
| 113 | + return ( |
| 114 | + <el-checkbox |
| 115 | + style={`padding-left: ${depth * 20}px`} |
| 116 | + checked={checked} |
| 117 | + onChange={() => store.toggleRowSelection(row)} |
| 118 | + /> |
| 119 | + ) |
| 120 | + } |
| 121 | + } |
| 122 | +}] |
21 | 123 | ``` |
22 | 124 |
|
23 | | -### Lints and fixes files |
| 125 | +- className |
| 126 | +- style |
| 127 | +- header, 顶部元素 |
| 128 | +- footer, 底部元素 |
| 129 | +- expandDepth: number, 指定默认渲染的树的递归深度 |
| 130 | +- expandRows: Array<RowModel>, 指定默认递归展开的行 |
| 131 | +- selectRows: Array<RowModel>, 指定默认选中的行 |
| 132 | + |
| 133 | + |
| 134 | +## Events |
| 135 | +| 事件名 | 说明 | 参数 | |
| 136 | +| ------------ | :----- | :----- | |
| 137 | +| expand-change | 当用户对某一行展开或者关闭的时候会触发该事件 | (row, expandRows) | |
| 138 | +| select-change | 当用户手动勾选数据行的 Checkbox 时触发的事件 | (row, selectRows) | |
| 139 | + |
| 140 | + |
| 141 | +## TODO |
| 142 | + |
| 143 | +- [x] 支持 expandDepth |
| 144 | +- [x] 支持 selectRows |
| 145 | +- [ ] 支持 列筛选 => column.filter(): void ? |
| 146 | +- [ ] 支持 列排序 => Column ? |
| 147 | + |
| 148 | + |
| 149 | +## Run |
| 150 | +```bash |
| 151 | +npm i |
24 | 152 | ``` |
25 | | -yarn run lint |
| 153 | + |
| 154 | +```bash |
| 155 | +npm run serve |
26 | 156 | ``` |
27 | 157 |
|
28 | | -### Customize configuration |
29 | | -See [Configuration Reference](https://cli.vuejs.org/config/). |
| 158 | + |
| 159 | +## License |
| 160 | +MIT |
0 commit comments