Commit 34ee7b4a14b4eb6db62def19528fe2c9c0758c13
1 parent
bb71140e
support Tree & add dispatch and broadcast methods
support Tree,many component add name $option;add dispatch and broadcast methods, mixins it
Showing
28 changed files
with
190 additions
and
69 deletions
Show diff stats
CHANGE.md
| ... | ... | @@ -21,4 +21,6 @@ class 改为了 className |
| 21 | 21 | ### Collapse |
| 22 | 22 | 废弃 activeKey,使用 v-model,key 是保留的,更名为 name |
| 23 | 23 | ### Carousel |
| 24 | -废弃 activeIndex,使用 v-model,v-for="n in slides.length",Vue2的数字循环,是从1开始的 | |
| 25 | 24 | \ No newline at end of file |
| 25 | +废弃 activeIndex,使用 v-model,v-for="n in slides.length",Vue2的数字循环,是从1开始的 | |
| 26 | +### Tree | |
| 27 | +废弃 data,改为 value,使用 v-model,key 更名为 name | |
| 26 | 28 | \ No newline at end of file | ... | ... |
README.md
src/components/alert/alert.vue
src/components/badge/badge.vue
src/components/button/button-group.vue
src/components/cascader/cascader.vue
src/components/checkbox/checkbox-group.vue
src/components/circle/circle.vue
src/components/collapse/collapse.vue
src/components/collapse/panel.vue
src/components/grid/col.vue
src/components/grid/row.vue
src/components/input-number/input-number.vue
src/components/radio/radio-group.vue
src/components/steps/step.vue
src/components/steps/steps.vue
src/components/switch/switch.vue
src/components/tag/tag.vue
src/components/timeline/timeline-item.vue
src/components/timeline/timeline.vue
src/components/tree/tree.vue
| 1 | 1 | <template> |
| 2 | 2 | <ul :class="classes"> |
| 3 | - <li v-for="item in data" :class="itemCls(item)"> | |
| 4 | - <span :class="arrowCls(item)" @click="setExpand(item.disabled, $index)"> | |
| 3 | + <li v-for="(item, index) in data" :class="itemCls(item)"> | |
| 4 | + <span :class="arrowCls(item)" @click="setExpand(item.disabled, index)"> | |
| 5 | 5 | <Icon type="arrow-right-b"></Icon> |
| 6 | 6 | </span> |
| 7 | 7 | <Checkbox |
| 8 | 8 | v-if="showCheckbox" |
| 9 | - :checked="item.checked && item.childrenCheckedStatus == 2" | |
| 9 | + :value="item.checked && item.childrenCheckedStatus == 2" | |
| 10 | 10 | :disabled="item.disabled || item.disableCheckbox" |
| 11 | 11 | :indeterminate="item.checked && item.childrenCheckedStatus == 1" |
| 12 | - @click.prevent="setCheck(item.disabled||item.disableCheckbox,$index)"></Checkbox> | |
| 13 | - <a :class="titleCls(item)" @click="setSelect(item.disabled, $index)"> | |
| 12 | + @click.prevent="setCheck(item.disabled||item.disableCheckbox, index)"></Checkbox> | |
| 13 | + <a :class="titleCls(item)" @click="setSelect(item.disabled, index)"> | |
| 14 | 14 | <span :class="[prefixCls + '-title']" v-html="item.title"></span> |
| 15 | 15 | </a> |
| 16 | - <tree | |
| 17 | - v-if="!item.isLeaf" | |
| 18 | - v-show="item.expand" | |
| 19 | - :class="expandCls(item)" | |
| 20 | - :data.sync="item.children" | |
| 21 | - :key="this.key+'.'+$index" | |
| 22 | - :multiple="multiple" | |
| 23 | - :show-checkbox="showCheckbox" | |
| 24 | - transition="slide-up"></tree> | |
| 16 | + <transition name="slide-up"> | |
| 17 | + <Tree | |
| 18 | + v-if="!item.isLeaf" | |
| 19 | + v-show="item.expand" | |
| 20 | + :class="expandCls(item)" | |
| 21 | + :value="item.children" | |
| 22 | + :name="item.name+'.'+index" | |
| 23 | + :multiple="multiple" | |
| 24 | + :show-checkbox="showCheckbox"></Tree> | |
| 25 | + </transition> | |
| 25 | 26 | </li> |
| 26 | 27 | </ul> |
| 27 | 28 | </template> |
| ... | ... | @@ -29,20 +30,22 @@ |
| 29 | 30 | import Icon from '../icon/icon.vue'; |
| 30 | 31 | import Checkbox from '../checkbox/checkbox.vue'; |
| 31 | 32 | import { t } from '../../locale'; |
| 33 | + import emitter from '../../mixins/emitter'; | |
| 32 | 34 | |
| 33 | 35 | const prefixCls = 'ivu-tree'; |
| 34 | 36 | |
| 35 | 37 | export default { |
| 36 | - name: 'tree', | |
| 38 | + name: 'Tree', | |
| 37 | 39 | components: { Icon, Checkbox }, |
| 40 | + mixins: [ emitter ], | |
| 38 | 41 | props: { |
| 39 | - data: { | |
| 42 | + value: { | |
| 40 | 43 | type: Array, |
| 41 | 44 | default () { |
| 42 | 45 | return []; |
| 43 | 46 | } |
| 44 | 47 | }, |
| 45 | - key: { | |
| 48 | + name: { | |
| 46 | 49 | type: String, |
| 47 | 50 | default: '0' |
| 48 | 51 | }, |
| ... | ... | @@ -63,12 +66,13 @@ |
| 63 | 66 | }, |
| 64 | 67 | data () { |
| 65 | 68 | return { |
| 66 | - prefixCls: prefixCls | |
| 69 | + prefixCls: prefixCls, | |
| 70 | + data: this.value | |
| 67 | 71 | }; |
| 68 | 72 | }, |
| 69 | 73 | computed: { |
| 70 | 74 | classes () { |
| 71 | - if (this.key === '0') { | |
| 75 | + if (this.name === '0') { | |
| 72 | 76 | return this.prefixCls; |
| 73 | 77 | } else { |
| 74 | 78 | return `${this.prefixCls}-child-tree`; |
| ... | ... | @@ -76,8 +80,11 @@ |
| 76 | 80 | } |
| 77 | 81 | }, |
| 78 | 82 | watch: { |
| 79 | - data(){ | |
| 80 | - if (this.key === '0') { | |
| 83 | + value (val) { | |
| 84 | + this.data = val; | |
| 85 | + }, | |
| 86 | + data () { | |
| 87 | + if (this.name === '0') { | |
| 81 | 88 | this.setKey(); |
| 82 | 89 | this.preHandle(); |
| 83 | 90 | } |
| ... | ... | @@ -118,55 +125,82 @@ |
| 118 | 125 | }, |
| 119 | 126 | setKey () { |
| 120 | 127 | for (let i = 0; i < this.data.length; i++) { |
| 121 | - this.data[i].key = `${this.key}.${i}`; | |
| 128 | + this.data[i].name = `${this.name}.${i}`; | |
| 122 | 129 | } |
| 123 | 130 | }, |
| 124 | 131 | preHandle () { |
| 125 | - for (let [i,item] of this.data.entries()) { | |
| 132 | + for (let [i, item] of this.data.entries()) { | |
| 126 | 133 | if (!item.children || !item.children.length) { |
| 127 | - this.$set(`data[${i}].isLeaf`, true); | |
| 128 | - this.$set(`data[${i}].childrenCheckedStatus`, 2); | |
| 134 | +// this.$set(`data[${i}].isLeaf`, true); | |
| 135 | +// this.$set(`data[${i}].childrenCheckedStatus`, 2); | |
| 136 | + this.$set(this.data[i], 'isLeaf', true); | |
| 137 | + this.$set(this.data[i], 'childrenCheckedStatus', 2); | |
| 129 | 138 | continue; |
| 130 | 139 | } |
| 131 | 140 | if (item.checked && !item.childrenCheckedStatus) { |
| 132 | - this.$set(`data[${i}].childrenCheckedStatus`, 2); | |
| 133 | - this.$broadcast('parentChecked', true, `${this.key}.${i}`); | |
| 141 | +// this.$set(`data[${i}].childrenCheckedStatus`, 2); | |
| 142 | + this.$set(this.data[i], 'childrenCheckedStatus', 2); | |
| 143 | +// this.$broadcast('parentChecked', true, `${this.name}.${i}`); | |
| 144 | + this.broadcast('Tree', 'parentChecked', { | |
| 145 | + status: true, | |
| 146 | + name: `${this.name}.${i}` | |
| 147 | + }); | |
| 134 | 148 | } else { |
| 135 | 149 | let status = this.getChildrenCheckedStatus(item.children); |
| 136 | - this.$set(`data[${i}].childrenCheckedStatus`, status); | |
| 137 | - if (status !== 0) this.$set(`data[${i}].checked`, true); | |
| 150 | +// this.$set(`data[${i}].childrenCheckedStatus`, status); | |
| 151 | + this.$set(this.data[i], 'childrenCheckedStatus', status); | |
| 152 | +// if (status !== 0) this.$set(`data[${i}].checked`, true); | |
| 153 | + if (status !== 0) this.$set(this.data[i], 'checked', true); | |
| 138 | 154 | } |
| 139 | 155 | } |
| 140 | 156 | }, |
| 141 | 157 | setExpand (disabled, index) { |
| 142 | 158 | if (!disabled) { |
| 143 | - this.$set(`data[${index}].expand`, !this.data[index].expand); | |
| 159 | +// this.$set(`data[${index}].expand`, !this.data[index].expand); | |
| 160 | + this.$set(this.data[index], 'expand', !this.data[index].expand); | |
| 144 | 161 | } |
| 145 | 162 | }, |
| 146 | 163 | setSelect (disabled, index) { |
| 147 | 164 | if (!disabled) { |
| 148 | 165 | const selected = !this.data[index].selected; |
| 149 | 166 | if (this.multiple || !selected) { |
| 150 | - this.$set(`data[${index}].selected`, selected); | |
| 167 | +// this.$set(`data[${index}].selected`, selected); | |
| 168 | + this.$set(this.data[index], 'selected', selected); | |
| 151 | 169 | } else { |
| 152 | 170 | for (let i = 0; i < this.data.length; i++) { |
| 153 | 171 | if (i == index) { |
| 154 | - this.$set(`data[${i}].selected`, true); | |
| 172 | +// this.$set(`data[${i}].selected`, true); | |
| 173 | + this.$set(this.data[i], 'selected', true); | |
| 155 | 174 | } else { |
| 156 | - this.$set(`data[${i}].selected`, false); | |
| 175 | +// this.$set(`data[${i}].selected`, false); | |
| 176 | + this.$set(this.data[i], 'selected', false); | |
| 157 | 177 | } |
| 158 | 178 | } |
| 159 | 179 | } |
| 160 | - this.$dispatch('nodeSelected', this, selected); | |
| 180 | +// this.$dispatch('nodeSelected', this, selected); | |
| 181 | + this.dispatch('Tree', 'nodeSelected', { | |
| 182 | + ori: this, | |
| 183 | + selected: selected | |
| 184 | + }) | |
| 161 | 185 | } |
| 162 | 186 | }, |
| 163 | 187 | setCheck (disabled, index) { |
| 164 | 188 | if (disabled) return; |
| 165 | 189 | const checked = !this.data[index].checked; |
| 166 | - this.$set(`data[${index}].checked`, checked); | |
| 167 | - this.$set(`data[${index}].childrenCheckedStatus`, checked ? 2 : 0); | |
| 168 | - this.$dispatch('childChecked', this, this.key); | |
| 169 | - this.$broadcast('parentChecked', checked, `${this.key}.${index}`); | |
| 190 | +// this.$set(`data[${index}].checked`, checked); | |
| 191 | + this.$set(this.data[index], 'checked', checked); | |
| 192 | +// this.$set(`data[${index}].childrenCheckedStatus`, checked ? 2 : 0); | |
| 193 | + this.$set(this.data[index], 'childrenCheckedStatus', checked ? 2 : 0); | |
| 194 | +// this.$dispatch('childChecked', this, this.name); | |
| 195 | + this.dispatch('Tree', 'childChecked', { | |
| 196 | + ori: this, | |
| 197 | + name: this.name | |
| 198 | + }); | |
| 199 | +// this.$broadcast('parentChecked', checked, `${this.name}.${index}`); | |
| 200 | + this.broadcast('Tree', 'parentChecked', { | |
| 201 | + status: checked, | |
| 202 | + name: `${this.name}.${index}` | |
| 203 | + }); | |
| 170 | 204 | }, |
| 171 | 205 | getNodes (data, opt) { |
| 172 | 206 | data = data || this.data; |
| ... | ... | @@ -215,55 +249,83 @@ |
| 215 | 249 | } |
| 216 | 250 | } |
| 217 | 251 | }, |
| 218 | - ready(){ | |
| 252 | + mounted () { | |
| 219 | 253 | this.setKey(); |
| 220 | 254 | this.preHandle(); |
| 221 | 255 | |
| 222 | - this.$on('nodeSelected', (ori, selected) => { | |
| 223 | - if (this.key !== '0') return true; | |
| 256 | +// this.$on('nodeSelected', (ori, selected) => { | |
| 257 | + this.$on('nodeSelected', (params) => { | |
| 258 | + const ori = params.ori; | |
| 259 | + const selected = params.selected; | |
| 260 | + | |
| 261 | + if (this.name !== '0') return true; | |
| 224 | 262 | if (!this.multiple && selected) { |
| 225 | 263 | if (this !== ori) { |
| 226 | 264 | for (let i = 0; i < this.data.length; i++) { |
| 227 | - this.$set(`data[${i}].selected`, false); | |
| 265 | +// this.$set(`data[${i}].selected`, false); | |
| 266 | + this.$set(this.data[i], 'selected', false); | |
| 228 | 267 | } |
| 229 | 268 | } |
| 230 | - this.$broadcast('cancelSelected', ori); | |
| 269 | +// this.$broadcast('cancelSelected', ori); | |
| 270 | + this.broadcast('Tree', 'cancelSelected', ori); | |
| 231 | 271 | } |
| 232 | 272 | this.$nextTick(() => { |
| 233 | 273 | this.$emit('on-select-change', this.getSelectedNodes()); |
| 234 | 274 | }); |
| 235 | 275 | }); |
| 236 | 276 | this.$on('cancelSelected', ori => { |
| 237 | - this.$broadcast('cancelSelected', ori); | |
| 277 | +// this.$broadcast('cancelSelected', ori); | |
| 278 | + this.broadcast('Tree', 'cancelSelected', ori); | |
| 238 | 279 | if (this !== ori) { |
| 239 | 280 | for (let i = 0; i < this.data.length; i++) { |
| 240 | - this.$set(`data[${i}].selected`, false); | |
| 281 | +// this.$set(`data[${i}].selected`, false); | |
| 282 | + this.$set(this.data[i], 'selected', false); | |
| 241 | 283 | } |
| 242 | 284 | } |
| 243 | 285 | }); |
| 244 | - this.$on('parentChecked', (status, key) => { | |
| 245 | - if (this.key == key || this.key.startsWith(key + '.')) { | |
| 286 | +// this.$on('parentChecked', (status, name) => { | |
| 287 | + this.$on('parentChecked', (params) => { | |
| 288 | + const status = params.status; | |
| 289 | + const name = params.name; | |
| 290 | + | |
| 291 | + if (this.name == name || this.name.startsWith(name + '.')) { | |
| 246 | 292 | for (let i = 0; i < this.data.length; i++) { |
| 247 | - this.$set(`data[${i}].checked`, status); | |
| 248 | - this.$set(`data[${i}].childrenCheckedStatus`, status ? 2 : 0); | |
| 293 | +// this.$set(`data[${i}].checked`, status); | |
| 294 | + this.$set(this.data[i], 'checked', status); | |
| 295 | +// this.$set(`data[${i}].childrenCheckedStatus`, status ? 2 : 0); | |
| 296 | + this.$set(this.data[i], 'childrenCheckedStatus', status ? 2 : 0); | |
| 249 | 297 | } |
| 250 | - this.$broadcast('parentChecked', status, key); | |
| 298 | +// this.$broadcast('parentChecked', status, name); | |
| 299 | + this.broadcast('Tree', 'parentChecked', { | |
| 300 | + status: status, | |
| 301 | + name: name | |
| 302 | + }); | |
| 251 | 303 | } |
| 252 | 304 | }); |
| 253 | - this.$on('childChecked', (ori, key) => { | |
| 254 | - if (this.key === '0') { | |
| 305 | +// this.$on('childChecked', (ori, name) => { | |
| 306 | + this.$on('childChecked', (params) => { | |
| 307 | + const ori = params.ori; | |
| 308 | + const name = params.name; | |
| 309 | + | |
| 310 | + if (this.name === '0') { | |
| 255 | 311 | this.$nextTick(() => { |
| 256 | 312 | this.$emit('on-check-change', this.getCheckedNodes()); |
| 257 | 313 | }); |
| 258 | 314 | } |
| 259 | 315 | if (this === ori) return; |
| 260 | 316 | for (let [i,item] of this.data.entries()) { |
| 261 | - if (this.key + '.' + i == key) { | |
| 317 | + if (this.name + '.' + i == name) { | |
| 262 | 318 | let temp = this.getChildrenCheckedStatus(item.children); |
| 263 | 319 | if (temp != item.childrenCheckedStatus) { |
| 264 | - this.$set(`data[${i}].checked`, !!temp); | |
| 265 | - this.$set(`data[${i}].childrenCheckedStatus`, temp); | |
| 266 | - if (this.key !== '0') this.$dispatch('childChecked', this, this.key); | |
| 320 | +// this.$set(`data[${i}].checked`, !!temp); | |
| 321 | + this.$set(this.data[i], 'checked', !!temp); | |
| 322 | +// this.$set(`data[${i}].childrenCheckedStatus`, temp); | |
| 323 | + this.$set(this.data[i], 'childrenCheckedStatus', temp); | |
| 324 | +// if (this.name !== '0') this.$dispatch('childChecked', this, this.name); | |
| 325 | + if (this.name !== '0') this.dispatch('Tree', 'childChecked', { | |
| 326 | + ori: this, | |
| 327 | + name: this.name | |
| 328 | + }); | |
| 267 | 329 | } |
| 268 | 330 | } |
| 269 | 331 | } | ... | ... |
src/components/upload/upload-list.vue
src/components/upload/upload.vue
src/index.js
| ... | ... | @@ -40,7 +40,7 @@ import Timeline from './components/timeline'; |
| 40 | 40 | // import TimePicker from './components/time-picker'; |
| 41 | 41 | // import Tooltip from './components/tooltip'; |
| 42 | 42 | // import Transfer from './components/transfer'; |
| 43 | -// import Tree from './components/tree'; | |
| 43 | +import Tree from './components/tree'; | |
| 44 | 44 | import Upload from './components/upload'; |
| 45 | 45 | import { Row, Col } from './components/grid'; |
| 46 | 46 | // import { Select, Option, OptionGroup } from './components/select'; |
| ... | ... | @@ -108,7 +108,7 @@ const iview = { |
| 108 | 108 | // TimePicker, |
| 109 | 109 | // Tooltip, |
| 110 | 110 | // Transfer, |
| 111 | - // Tree, | |
| 111 | + Tree, | |
| 112 | 112 | Upload |
| 113 | 113 | }; |
| 114 | 114 | ... | ... |
| 1 | +function broadcast(componentName, eventName, params) { | |
| 2 | + this.$children.forEach(child => { | |
| 3 | + const name = child.$options.name; | |
| 4 | + | |
| 5 | + if (name === componentName) { | |
| 6 | + child.$emit.apply(child, [eventName].concat(params)); | |
| 7 | + } else { | |
| 8 | + broadcast.apply(child, [componentName, eventName].concat([params])); | |
| 9 | + } | |
| 10 | + }); | |
| 11 | +} | |
| 12 | +export default { | |
| 13 | + methods: { | |
| 14 | + dispatch(componentName, eventName, params) { | |
| 15 | + let parent = this.$parent || this.$root; | |
| 16 | + let name = parent.$options.name; | |
| 17 | + | |
| 18 | + while (parent && (!name || name !== componentName)) { | |
| 19 | + parent = parent.$parent; | |
| 20 | + | |
| 21 | + if (parent) { | |
| 22 | + name = parent.$options.name; | |
| 23 | + } | |
| 24 | + } | |
| 25 | + if (parent) { | |
| 26 | + parent.$emit.apply(parent, [eventName].concat(params)); | |
| 27 | + } | |
| 28 | + }, | |
| 29 | + broadcast(componentName, eventName, params) { | |
| 30 | + broadcast.call(this, componentName, eventName, params); | |
| 31 | + } | |
| 32 | + } | |
| 33 | +}; | |
| 0 | 34 | \ No newline at end of file | ... | ... |
test/app.vue
| ... | ... | @@ -30,6 +30,7 @@ li + li { border-left: solid 1px #bbb; padding-left: 10px; margin-left: 10px; } |
| 30 | 30 | <li><router-link to="/upload">Upload</router-link></li> |
| 31 | 31 | <li><router-link to="/collapse">Collapse</router-link></li> |
| 32 | 32 | <li><router-link to="/carousel">Carousel</router-link></li> |
| 33 | + <li><router-link to="/tree">Tree</router-link></li> | |
| 33 | 34 | </ul> |
| 34 | 35 | </nav> |
| 35 | 36 | <router-view></router-view> | ... | ... |
test/main.js
test/routers/tree.vue
| 1 | 1 | <template> |
| 2 | - <Tree | |
| 3 | - :data.sync="treeData" | |
| 4 | - :show-checkbox="true" | |
| 5 | - :multiple="true" | |
| 6 | - @on-select-change="selectFn" | |
| 7 | - @on-check-change="checkFn"></Tree> | |
| 2 | + <div> | |
| 3 | + <Tree | |
| 4 | + v-model="treeData" | |
| 5 | + :show-checkbox="true" | |
| 6 | + :multiple="true" | |
| 7 | + @on-select-change="selectFn" | |
| 8 | + @on-check-change="checkFn"></Tree> | |
| 9 | + </div> | |
| 8 | 10 | </template> |
| 9 | 11 | <script> |
| 10 | 12 | export default { | ... | ... |