5
5
'vjs-tree': true,
6
6
'is-virtual': virtual,
7
7
}"
8
- @scroll =" onTreeScroll"
8
+ @scroll =" virtual ? onTreeScroll() : undefined "
9
9
>
10
- <div :style =" virtual && { height: `${flatData.length * itemHeight}px` }" >
11
- <div :style =" virtual && { transform: `translateY(${translateY}px)` }" >
12
- <tree-node
13
- v-for =" item in visibleData"
14
- :key =" item.id"
15
- :node =" item"
16
- :collapsed =" !!hiddenPaths[item.path]"
17
- :custom-value-formatter =" customValueFormatter"
18
- :show-double-quotes =" showDoubleQuotes"
19
- :show-length =" showLength"
20
- :collapsed-on-click-brackets =" collapsedOnClickBrackets"
21
- :checked =" selectedPaths.includes(item.path)"
22
- :selectable-type =" selectableType"
23
- :show-line =" showLine"
24
- :show-select-controller =" showSelectController"
25
- :select-on-click-node =" selectOnClickNode"
26
- :path-selectable =" pathSelectable"
27
- :highlight-selected-node =" highlightSelectedNode"
28
- @tree-node-click =" onTreeNodeClick"
29
- @brackets-click =" onBracketsClick"
30
- @selected-change =" onSelectedChange"
31
- />
10
+ <div class =" vjs-tree-list" :style =" virtual && { height: `${height}px` }" >
11
+ <div
12
+ class =" vjs-tree-list__holder"
13
+ :style =" virtual && { height: `${flatData.length * itemHeight}px` }"
14
+ >
15
+ <div
16
+ class =" vjs-tree-list__holder-inner"
17
+ :style =" virtual && { transform: `translateY(${translateY}px)` }"
18
+ >
19
+ <tree-node
20
+ v-for =" item in visibleData"
21
+ :key =" item.id"
22
+ :node =" item"
23
+ :collapsed =" !!hiddenPaths[item.path]"
24
+ :custom-value-formatter =" customValueFormatter"
25
+ :show-double-quotes =" showDoubleQuotes"
26
+ :show-length =" showLength"
27
+ :collapsed-on-click-brackets =" collapsedOnClickBrackets"
28
+ :checked =" selectedPaths.includes(item.path)"
29
+ :selectable-type =" selectableType"
30
+ :show-line =" showLine"
31
+ :show-select-controller =" showSelectController"
32
+ :select-on-click-node =" selectOnClickNode"
33
+ :path-selectable =" pathSelectable"
34
+ :highlight-selected-node =" highlightSelectedNode"
35
+ @tree-node-click =" onTreeNodeClick"
36
+ @brackets-click =" onBracketsClick"
37
+ @selected-change =" onSelectedChange"
38
+ :style =" itemHeight && itemHeight !== 20 ? { lineHeight: `${itemHeight}px` } : {}"
39
+ />
40
+ </div >
32
41
</div >
33
42
</div >
34
43
</div >
35
44
</template >
36
45
37
46
<script >
38
47
import TreeNode from ' src/components/TreeNode' ;
39
- import { getDataType , jsonFlatten } from ' src/utils' ;
48
+ import { jsonFlatten } from ' src/utils' ;
40
49
import ' ./styles.less' ;
41
50
42
51
export default {
@@ -45,12 +54,11 @@ export default {
45
54
TreeNode,
46
55
},
47
56
props: {
48
- // 当前树的数据
57
+ // JSON
49
58
data: {
50
59
type: [String , Number , Boolean , Array , Object ],
51
60
default: null ,
52
61
},
53
- // 定义树的深度, 大于该深度的子树将不被展开
54
62
deep: {
55
63
type: Number ,
56
64
default: Infinity ,
@@ -59,7 +67,7 @@ export default {
59
67
type: Boolean ,
60
68
default: false ,
61
69
},
62
- // 数据层级顶级路径
70
+ // define root path
63
71
path: {
64
72
type: String ,
65
73
default: ' root' ,
@@ -68,26 +76,31 @@ export default {
68
76
type: Boolean ,
69
77
default: false ,
70
78
},
79
+ // When using virtual scroll, set the height of tree.
80
+ height: {
81
+ type: Number ,
82
+ default: 400 ,
83
+ },
84
+ // When using virtual scroll, define the height of each row.
71
85
itemHeight: {
72
86
type: Number ,
73
87
default: 20 ,
74
88
},
75
- // 是否显示数组|对象的长度
76
89
showLength: {
77
90
type: Boolean ,
78
91
default: false ,
79
92
},
80
- // key名是否显示双引号
93
+ // showDoubleQuotes on key
81
94
showDoubleQuotes: {
82
95
type: Boolean ,
83
96
default: true ,
84
97
},
85
- // 定义数据层级支持的选中方式, 默认无该功能
98
+ // Define the selection method supported by the data level, which is not available by default.
86
99
selectableType: {
87
100
type: String ,
88
101
default: ' ' , // ''|multiple|single
89
102
},
90
- // 是否展示左侧选择控件
103
+ // Whether to display the selection control.
91
104
showSelectController: {
92
105
type: Boolean ,
93
106
default: false ,
@@ -96,18 +109,18 @@ export default {
96
109
type: Boolean ,
97
110
default: true ,
98
111
},
99
- // 是否在点击树的时候选中节点
112
+ // Whether to trigger selection when clicking on the node.
100
113
selectOnClickNode: {
101
114
type: Boolean ,
102
115
default: true ,
103
116
},
104
- // 存在选择功能时, 定义已选中的数据层级
105
- // 多选时为数组 ['root.a', 'root.b'], 单选时为字符串 'root.a'
117
+ // When there is a selection function, define the selected path.
118
+ // For multiple selections, it is an array ['root.a','root.b'], for single selection, it is a string of 'root.a'.
106
119
value: {
107
120
type: [Array , String ],
108
121
default : () => ' ' ,
109
122
},
110
- // 定义某个数据层级是否支持选中操作
123
+ // When using the selectableType, define whether current path/content is enabled.
111
124
pathSelectable: {
112
125
type: Function ,
113
126
default : () => true ,
@@ -127,11 +140,6 @@ export default {
127
140
type: Function ,
128
141
default: null ,
129
142
},
130
- // Number of lines to show when virtual is true
131
- virtualLines: {
132
- type: Number ,
133
- default: 10
134
- }
135
143
},
136
144
data () {
137
145
return {
@@ -141,10 +149,7 @@ export default {
141
149
const depthComparison = this .deepCollapseChildren
142
150
? item .level >= this .deep
143
151
: item .level === this .deep ;
144
- if (
145
- (item .type === ' objectStart' || item .type === ' arrayStart' ) &&
146
- depthComparison
147
- ) {
152
+ if ((item .type === ' objectStart' || item .type === ' arrayStart' ) && depthComparison) {
148
153
return {
149
154
... acc,
150
155
[item .path ]: 1 ,
@@ -155,31 +160,41 @@ export default {
155
160
};
156
161
},
157
162
computed: {
158
- flatData () {
163
+ originFlatData () {
164
+ return jsonFlatten (this .data , this .path );
165
+ },
166
+
167
+ flatData ({ originFlatData, hiddenPaths }) {
168
+ // Avoid accessing `this` in a loop to improve performance
159
169
let startHiddenItem = null ;
160
- const data = jsonFlatten (this .data , this .path ).reduce ((acc , cur , index ) => {
170
+ const data = [];
171
+ const length = originFlatData .length ;
172
+ for (let i = 0 ; i < length; i++ ) {
173
+ const cur = originFlatData[i];
161
174
const item = {
162
175
... cur,
163
- id: index ,
176
+ id: i ,
164
177
};
165
- const isHidden = this . hiddenPaths [item .path ];
178
+ const isHidden = hiddenPaths[item .path ];
166
179
if (startHiddenItem && startHiddenItem .path === item .path ) {
167
180
const isObject = startHiddenItem .type === ' objectStart' ;
168
181
const mergeItem = {
169
- ... startHiddenItem,
170
182
... item,
183
+ ... startHiddenItem,
184
+ showComma: item .showComma ,
171
185
content: isObject ? ' {...}' : ' [...]' ,
172
186
type: isObject ? ' objectCollapsed' : ' arrayCollapsed' ,
173
187
};
174
188
startHiddenItem = null ;
175
- return acc . concat (mergeItem);
189
+ data . push (mergeItem);
176
190
} else if (isHidden && ! startHiddenItem) {
177
191
startHiddenItem = item;
178
- return acc;
192
+ continue ;
193
+ } else {
194
+ if (startHiddenItem) continue ;
195
+ else data .push (item);
179
196
}
180
-
181
- return startHiddenItem ? acc : acc .concat (item);
182
- }, []);
197
+ }
183
198
return data;
184
199
},
185
200
@@ -213,39 +228,43 @@ export default {
213
228
},
214
229
215
230
flatData: {
216
- handler () {
217
- this .onTreeScroll ( );
231
+ handler (val ) {
232
+ this .updateVisibleData (val );
218
233
},
219
234
immediate: true ,
220
235
},
221
236
},
222
237
methods: {
223
- onTreeScroll ( ) {
238
+ updateVisibleData ( flatDataValue ) {
224
239
if (this .virtual ) {
225
- const visibleCount = this .virtualLines ;
240
+ const visibleCount = this .height / this . itemHeight ;
226
241
const scrollTop = (this .$refs .tree && this .$refs .tree .scrollTop ) || 0 ;
227
242
const scrollCount = Math .floor (scrollTop / this .itemHeight );
228
243
let start =
229
244
scrollCount < 0
230
245
? 0
231
- : scrollCount + visibleCount > this . flatData .length
232
- ? this . flatData .length - visibleCount
246
+ : scrollCount + visibleCount > flatDataValue .length
247
+ ? flatDataValue .length - visibleCount
233
248
: scrollCount;
234
249
if (start < 0 ) {
235
250
start = 0 ;
236
251
}
237
252
const end = start + visibleCount;
238
253
this .translateY = start * this .itemHeight ;
239
- this .visibleData = this . flatData .filter ((item , index ) => index >= start && index < end);
254
+ this .visibleData = flatDataValue .filter ((item , index ) => index >= start && index < end);
240
255
} else {
241
- this .visibleData = this . flatData ;
256
+ this .visibleData = flatDataValue ;
242
257
}
243
258
},
244
259
260
+ onTreeScroll () {
261
+ this .updateVisibleData (this .flatData );
262
+ },
263
+
245
264
onSelectedChange ({ path }) {
246
265
const type = this .selectableType ;
247
266
if (type === ' multiple' ) {
248
- const index = this .selectedPaths .findIndex (item => item === path);
267
+ const index = this .selectedPaths .findIndex (( item ) => item === path);
249
268
const oldVal = [... this .selectedPaths ];
250
269
if (index !== - 1 ) {
251
270
this .selectedPaths .splice (index, 1 );
0 commit comments