Blame view

src/components/tree/tree.vue 6.54 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
e81207a2   梁灏   update Tree
42
43
              }
          },
89f2ba8b   梁灏   init Tree component
44
          data () {
e81207a2   梁灏   update Tree
45
              return {
d44420be   Sergio Crisostomo   refactor and make...
46
                  prefixCls: prefixCls,
0a8f9b43   Sergio Crisostomo   Keep original dat...
47
                  stateTree: this.data,
d44420be   Sergio Crisostomo   refactor and make...
48
                  flatState: [],
e81207a2   梁灏   update Tree
49
              };
89f2ba8b   梁灏   init Tree component
50
          },
d44420be   Sergio Crisostomo   refactor and make...
51
          watch: {
76a47814   梁灏   fixed #2128
52
53
54
55
56
57
58
              data: {
                  deep: true,
                  handler () {
                      this.stateTree = this.data;
                      this.flatState = this.compileFlatState();
                      this.rebuildTree();
                  }
d44420be   Sergio Crisostomo   refactor and make...
59
60
              }
          },
e5337c81   梁灏   fixed some compon...
61
62
          computed: {
              localeEmptyText () {
d44420be   Sergio Crisostomo   refactor and make...
63
                  if (typeof this.emptyText === 'undefined') {
e5337c81   梁灏   fixed some compon...
64
65
66
67
                      return this.t('i.tree.emptyText');
                  } else {
                      return this.emptyText;
                  }
d44420be   Sergio Crisostomo   refactor and make...
68
              },
e5337c81   梁灏   fixed some compon...
69
          },
e81207a2   梁灏   update Tree
70
          methods: {
d44420be   Sergio Crisostomo   refactor and make...
71
72
73
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
              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...
115
                      if (!parentKey && parentKey !== 0) return;
d44420be   Sergio Crisostomo   refactor and make...
116
117
118
119
120
121
122
123
                      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
124
              getSelectedNodes () {
d44420be   Sergio Crisostomo   refactor and make...
125
126
                  /* public API */
                  return this.flatState.filter(obj => obj.node.selected).map(obj => obj.node);
cb84e64a   梁灏   update Tree
127
              },
53754a31   梁灏   fixed #468
128
              getCheckedNodes () {
d44420be   Sergio Crisostomo   refactor and make...
129
130
                  /* public API */
                  return this.flatState.filter(obj => obj.node.checked).map(obj => obj.node);
53754a31   梁灏   fixed #468
131
              },
d44420be   Sergio Crisostomo   refactor and make...
132
133
134
              updateTreeDown(node, changes = {}) {
                  for (let key in changes) {
                      this.$set(node, key, changes[key]);
e81207a2   梁灏   update Tree
135
                  }
d44420be   Sergio Crisostomo   refactor and make...
136
137
138
139
                  if (node.children) {
                      node.children.forEach(child => {
                          this.updateTreeDown(child, changes);
                      });
e81207a2   梁灏   update Tree
140
                  }
d44420be   Sergio Crisostomo   refactor and make...
141
142
143
144
145
146
147
148
149
              },
              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
150
                  this.$emit('on-select-change', this.getSelectedNodes());
d44420be   Sergio Crisostomo   refactor and make...
151
152
153
154
155
156
157
158
159
              },
              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
160
                  this.$emit('on-check-change', this.getCheckedNodes());
69a10b78   梁灏   fixed #787
161
              }
d44420be   Sergio Crisostomo   refactor and make...
162
163
164
165
166
167
168
169
170
          },
          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
171
          }
89f2ba8b   梁灏   init Tree component
172
      };
d44420be   Sergio Crisostomo   refactor and make...
173
  </script>