Skip to content

Commit 26e0197

Browse files
author
weibangtuo
committed
Support asynchronous loading tree data
1 parent 3fb6c43 commit 26e0197

File tree

3 files changed

+63
-19
lines changed

3 files changed

+63
-19
lines changed

README.md

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,26 +38,31 @@ Add the component in your vue view.
3838
3939
## Node Options
4040
41+
`[opt]` means optional property.
42+
4143
```javascript
4244
{
4345
name: 'Node Name',
4446
title: 'Node Tag title attr',
45-
isParent: true, //
46-
isOpen: true, // Control node to fold or unfold
47-
icon: 'fa fa-folder', // Or other custom icons call by class name
48-
openedIcon: 'fa fa-folder-open', // [option] For parent. Show when isOpen == true, show icon if it's null or empty
49-
closedIcon: 'fa fa-folder', // [option] For parent. Show when isOpen != true, show icon if it's null or empty
50-
children: [], // for parent node only
51-
buttons: [ // []
47+
isParent: true, // Requested for parent node
48+
isOpen: false, // [opt] Control node to fold or unfold
49+
icon: 'fa fa-folder', //[opt] Icon class name
50+
openedIcon: 'fa fa-folder-open', // [opt] For parent. Show when isOpen == true, show icon if it's null or empty
51+
closedIcon: 'fa fa-folder', // [opt] For parent. Show when isOpen != true, show icon if it's null or empty
52+
children: [], // Requested for parent node
53+
buttons: [ // [opt]
5254
{
53-
title: 'icon button tag title attr', //[option]
55+
title: 'icon button tag title attr', //[opt]
5456
icon: 'fa fa-edit',
55-
click: function (node) { //[option]
57+
click: function (node) { //[opt]
5658
//
5759
}
5860
}
5961
//...
60-
]
62+
],
63+
showLoading: false, // [opt] For parent, when `node.showLoading && node._loading` and node is opened then show loading icon
64+
onOpened: function (node) {}, // [opt]
65+
onClosed: function (node) {} // [opt]
6166
}
6267
```
6368

demo/demo.js

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
node.children.push({
66
name: 'child node',
77
parent: node,
8-
isOpen: true,
98
isParent: true,
109
children: [],
1110
buttons: [
@@ -78,7 +77,6 @@
7877
},
7978
{
8079
name: 'Level1 add node',
81-
isOpen: true,
8280
isParent: true,
8381
children: [],
8482
buttons: [
@@ -88,7 +86,7 @@
8886
click: function (node) {
8987
node.isOpen = true;
9088
node.children.push({
91-
name: 'level2 node',
89+
name: 'Level2 node',
9290
parent: node,
9391
buttons: [
9492
{
@@ -105,8 +103,7 @@
105103
]
106104
},
107105
{
108-
name: 'level1-addNode',
109-
isOpen: true,
106+
name: 'Level1-addNode',
110107
isParent: true,
111108
children: [],
112109
buttons: [
@@ -116,6 +113,27 @@
116113
click: addNode
117114
}
118115
]
116+
},
117+
{
118+
name: 'Level1 Ajax',
119+
isParent: true,
120+
children: [],
121+
showLoading: true, // if (node.showLoading && node._loading) then show loading icon
122+
onOpened: function (node) {
123+
if (!node._loading) {
124+
Vue.set(node, 'children', []); // Clean old data
125+
node._loading = true; // Start Ajax
126+
setTimeout(function () { //
127+
node._loading = false; //Finish Ajax
128+
for (var i = 1; i < 6; i++) {
129+
node.children.push({name: 'Ajax Node ' + i});
130+
}
131+
}, 2000);
132+
}
133+
},
134+
onClosed: function () {
135+
// NOOP
136+
}
119137
}
120138
]
121139
}

src/tree.vue.js

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
'use strict';
33
var VueTreeItem = Vue.extend({
44
template: '<li :class="{parent_li: node.isParent}">' +
5-
'<i v-if="node.isParent" v-on:click="click(node)" class="fa icon-open-state" :class=\'{"fa-plus-square-o": !node.isOpen, "fa-minus-square-o": node.isOpen}\'></i>' +
5+
'<i v-if="node.isParent" v-on:click="toggle(node)" class="fa icon-open-state" :class=\'{"fa-plus-square-o": !node.isOpen, "fa-minus-square-o": node.isOpen}\'></i>' +
66
'<span :title="node.title">' +
77
'<i v-if="showIcon(node)" :class="nodeClass(node)"></i> {{node.name}}</span>' +
88
'<a v-for="btn in node.buttons" class="ml5" href="javascript:" :title="btn.title" v-on:click="btnClick(btn, node)"><i :class="btn.icon"></i></a>' +
9-
'<ul v-if="node.children && node.children.length" v-show="node.isOpen">' +
9+
'<ul v-show="node.isOpen">' +
10+
'<li v-show="node.showLoading && node._loading"><i class="fa fa-spinner fa-pulse"></i></li>' +
1011
'<vue-tree-item v-for="item in node.children" :node="item"></vue-tree-item>' +
1112
'</ul>' +
1213
'</li>',
@@ -26,14 +27,34 @@
2627
return node.closedIcon || node.icon;
2728
}
2829
},
29-
click: function (node) {
30-
node.isOpen = !node.isOpen;
30+
toggle: function (node) {
31+
if (node.hasOwnProperty('isOpen')) {
32+
node.isOpen = !node.isOpen;
33+
} else {
34+
Vue.set(node, 'isOpen', true);
35+
}
3136
},
3237
btnClick: function (btn, node) {
3338
if (typeof btn.click === 'function') {
3439
btn.click(node);
3540
}
3641
}
42+
},
43+
watch: {
44+
'node.isOpen': function (val) {
45+
if (!this.node.hasOwnProperty('_loading')) {
46+
Vue.set(this.node, '_loading', false);
47+
}
48+
if (val) {
49+
if (typeof this.node.onOpened === 'function') {
50+
this.node.onOpened(this.node);
51+
}
52+
} else {
53+
if (typeof this.node.onClosed === 'function') {
54+
this.node.onClosed(this.node);
55+
}
56+
}
57+
}
3758
}
3859
});
3960
Vue.component('vue-tree-item', VueTreeItem);

0 commit comments

Comments
 (0)