Blame view

src/components/tree/tree.vue 6.61 KB
89f2ba8b   梁灏   init Tree component
1
  <template>
cb84e64a   梁灏   update Tree
2
3
      <div :class="prefixCls">
          <Tree-node
d44420be   Sergio Crisostomo   refactor and make...
4
              v-for="item in stateTree"
2e84df44   梁灏   fixed Tree key bu...
5
              :key="item.nodeKey"
cb84e64a   梁灏   update Tree
6
7
8
9
10
              :data="item"
              visible
              :multiple="multiple"
              :show-checkbox="showCheckbox">
          </Tree-node>
d44420be   Sergio Crisostomo   refactor and make...
11
          <div :class="[prefixCls + '-empty']" v-if="!stateTree.length">{{ localeEmptyText }}</div>
cb84e64a   梁灏   update Tree
12
      </div>
89f2ba8b   梁灏   init Tree component
13
14
  </template>
  <script>
cb84e64a   梁灏   update Tree
15
      import TreeNode from './node.vue';
e2c6ff2b   梁灏   update Rate
16
      import Emitter from '../../mixins/emitter';
e5337c81   梁灏   fixed some compon...
17
      import Locale from '../../mixins/locale';
e81207a2   梁灏   update Tree
18
19
20
  
      const prefixCls = 'ivu-tree';
  
89f2ba8b   梁灏   init Tree component
21
      export default {
34ee7b4a   梁灏   support Tree & ad...
22
          name: 'Tree',
e5337c81   梁灏   fixed some compon...
23
          mixins: [ Emitter, Locale ],
cb84e64a   梁灏   update Tree
24
          components: { TreeNode },
e81207a2   梁灏   update Tree
25
          props: {
9d79a51f   梁灏   update Tree
26
              data: {
e81207a2   梁灏   update Tree
27
28
29
30
31
                  type: Array,
                  default () {
                      return [];
                  }
              },
e81207a2   梁灏   update Tree
32
33
34
35
36
37
38
39
              multiple: {
                  type: Boolean,
                  default: false
              },
              showCheckbox: {
                  type: Boolean,
                  default: false
              },
e81207a2   梁灏   update Tree
40
              emptyText: {
e5337c81   梁灏   fixed some compon...
41
                  type: String
b31aab71   梁灏   Tree add async lo...
42
43
44
              },
              loadData: {
                  type: Function
e81207a2   梁灏   update Tree
45
46
              }
          },
89f2ba8b   梁灏   init Tree component
47
          data () {
e81207a2   梁灏   update Tree
48
              return {
d44420be   Sergio Crisostomo   refactor and make...
49
                  prefixCls: prefixCls,
0a8f9b43   Sergio Crisostomo   Keep original dat...
50
                  stateTree: this.data,
d44420be   Sergio Crisostomo   refactor and make...
51
                  flatState: [],
e81207a2   梁灏   update Tree
52
              };
89f2ba8b   梁灏   init Tree component
53
          },
d44420be   Sergio Crisostomo   refactor and make...
54
          watch: {
76a47814   梁灏   fixed #2128
55
56
57
58
59
60
61
              data: {
                  deep: true,
                  handler () {
                      this.stateTree = this.data;
                      this.flatState = this.compileFlatState();
                      this.rebuildTree();
                  }
d44420be   Sergio Crisostomo   refactor and make...
62
63
              }
          },
e5337c81   梁灏   fixed some compon...
64
65
          computed: {
              localeEmptyText () {
d44420be   Sergio Crisostomo   refactor and make...
66
                  if (typeof this.emptyText === 'undefined') {
e5337c81   梁灏   fixed some compon...
67
68
69
70
                      return this.t('i.tree.emptyText');
                  } else {
                      return this.emptyText;
                  }
d44420be   Sergio Crisostomo   refactor and make...
71
              },
e5337c81   梁灏   fixed some compon...
72
          },
e81207a2   梁灏   update Tree
73
          methods: {
d44420be   Sergio Crisostomo   refactor and make...
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
              compileFlatState () { // so we have always a relation parent/children of each node
                  let keyCounter = 0;
                  const flatTree = [];
                  function flattenChildren(node, parent) {
                      node.nodeKey = keyCounter++;
                      flatTree[node.nodeKey] = { node: node, nodeKey: node.nodeKey };
                      if (typeof parent != 'undefined') {
                          flatTree[node.nodeKey].parent = parent.nodeKey;
                          flatTree[parent.nodeKey].children.push(node.nodeKey);
                      }
  
                      if (node.children) {
                          flatTree[node.nodeKey].children = [];
                          node.children.forEach(child => flattenChildren(child, node));
                      }
                  }
                  this.stateTree.forEach(rootNode => {
                      flattenChildren(rootNode);
                  });
                  return flatTree;
              },
              updateTreeUp(nodeKey){
                  const parentKey = this.flatState[nodeKey].parent;
                  if (typeof parentKey == 'undefined') return;
  
                  const node = this.flatState[nodeKey].node;
                  const parent = this.flatState[parentKey].node;
                  if (node.checked == parent.checked && node.indeterminate == parent.indeterminate) return; // no need to update upwards
  
                  if (node.checked == true) {
                      this.$set(parent, 'checked', parent.children.every(node => node.checked));
                      this.$set(parent, 'indeterminate', !parent.checked);
                  } else {
                      this.$set(parent, 'checked', false);
                      this.$set(parent, 'indeterminate', parent.children.some(node => node.checked || node.indeterminate));
                  }
                  this.updateTreeUp(parentKey);
              },
              rebuildTree () { // only called when `data` prop changes
                  const checkedNodes = this.getCheckedNodes();
                  checkedNodes.forEach(node => {
                      this.updateTreeDown(node, {checked: true});
                      // propagate upwards
                      const parentKey = this.flatState[node.nodeKey].parent;
0a8f9b43   Sergio Crisostomo   Keep original dat...
118
                      if (!parentKey && parentKey !== 0) return;
d44420be   Sergio Crisostomo   refactor and make...
119
120
121
122
123
124
125
126
                      const parent = this.flatState[parentKey].node;
                      const childHasCheckSetter = typeof node.checked != 'undefined' && node.checked;
                      if (childHasCheckSetter && parent.checked != node.checked) {
                          this.updateTreeUp(node.nodeKey); // update tree upwards
                      }
                  });
              },
  
cb84e64a   梁灏   update Tree
127
              getSelectedNodes () {
d44420be   Sergio Crisostomo   refactor and make...
128
129
                  /* public API */
                  return this.flatState.filter(obj => obj.node.selected).map(obj => obj.node);
cb84e64a   梁灏   update Tree
130
              },
53754a31   梁灏   fixed #468
131
              getCheckedNodes () {
d44420be   Sergio Crisostomo   refactor and make...
132
133
                  /* public API */
                  return this.flatState.filter(obj => obj.node.checked).map(obj => obj.node);
53754a31   梁灏   fixed #468
134
              },
d44420be   Sergio Crisostomo   refactor and make...
135
136
137
              updateTreeDown(node, changes = {}) {
                  for (let key in changes) {
                      this.$set(node, key, changes[key]);
e81207a2   梁灏   update Tree
138
                  }
d44420be   Sergio Crisostomo   refactor and make...
139
140
141
142
                  if (node.children) {
                      node.children.forEach(child => {
                          this.updateTreeDown(child, changes);
                      });
e81207a2   梁灏   update Tree
143
                  }
d44420be   Sergio Crisostomo   refactor and make...
144
145
146
147
148
149
150
151
152
              },
              handleSelect (nodeKey) {
                  const node = this.flatState[nodeKey].node;
                  if (!this.multiple){ // reset selected
                      const currentSelectedKey = this.flatState.findIndex(obj => obj.node.selected);
                      if (currentSelectedKey >= 0) this.$set(this.flatState[currentSelectedKey].node, 'selected', false);
                  }
                  this.$set(node, 'selected', !node.selected);
  
cb84e64a   梁灏   update Tree
153
                  this.$emit('on-select-change', this.getSelectedNodes());
d44420be   Sergio Crisostomo   refactor and make...
154
155
156
157
158
159
160
161
162
              },
              handleCheck({ checked, nodeKey }) {
                  const node = this.flatState[nodeKey].node;
                  this.$set(node, 'checked', checked);
                  this.$set(node, 'indeterminate', false);
  
                  this.updateTreeUp(nodeKey); // propagate up
                  this.updateTreeDown(node, {checked, indeterminate: false}); // reset `indeterminate` when going down
  
53754a31   梁灏   fixed #468
163
                  this.$emit('on-check-change', this.getCheckedNodes());
69a10b78   梁灏   fixed #787
164
              }
d44420be   Sergio Crisostomo   refactor and make...
165
166
167
168
169
170
171
172
173
          },
          created(){
              this.flatState = this.compileFlatState();
              this.rebuildTree();
          },
          mounted () {
              this.$on('on-check', this.handleCheck);
              this.$on('on-selected', this.handleSelect);
              this.$on('toggle-expand', node => this.$emit('on-toggle-expand', node));
e81207a2   梁灏   update Tree
174
          }
89f2ba8b   梁灏   init Tree component
175
      };
d44420be   Sergio Crisostomo   refactor and make...
176
  </script>