Blame view

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