Blame view

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