Commit 933afc7a2ce26c15fb9996b8a15d8abc9f2106a8

Authored by 梁灏
1 parent a28bc982

fixed #950

examples/routers/cascader.vue
  1 +<!--<template>-->
  2 + <!--<Row>-->
  3 + <!--<i-col span="4">-->
  4 + <!--<Button @click="handleLoad">load</Button>-->
  5 + <!--{{ v1 }}-->
  6 + <!--</i-col>-->
  7 + <!--<i-col span="4">-->
  8 + <!--<Cascader :data="data2" filterable v-model="v1" style="width: 200px;"></Cascader>-->
  9 + <!--&lt;!&ndash;<Cascader :data="data2" filterable v-model="v1" :loadData="loadData"></Cascader>&ndash;&gt;-->
  10 + <!--</i-col>-->
  11 + <!--</Row>-->
  12 +<!--</template>-->
  13 +<!--<script>-->
  14 + <!--export default {-->
  15 + <!--data () {-->
  16 + <!--return {-->
  17 + <!--v1: [],-->
  18 + <!--data2: [-->
  19 + <!--{-->
  20 + <!--value: 'zhejiang',-->
  21 + <!--label: '浙江',-->
  22 + <!--children: [],-->
  23 + <!--loading: false-->
  24 + <!--},-->
  25 + <!--{-->
  26 + <!--value: 'jiangsu',-->
  27 + <!--label: '江苏',-->
  28 + <!--children: [{-->
  29 + <!--value: 'nanjing',-->
  30 + <!--label: '南京',-->
  31 + <!--children: [-->
  32 + <!--{-->
  33 + <!--value: 'zhonghuamen',-->
  34 + <!--label: '中华门'-->
  35 + <!--},-->
  36 + <!--{-->
  37 + <!--value: 'v1',-->
  38 + <!--label: 'v111'-->
  39 + <!--},-->
  40 + <!--{-->
  41 + <!--value: 'v2',-->
  42 + <!--label: 'v2222'-->
  43 + <!--},-->
  44 + <!--{-->
  45 + <!--value: 'v3',-->
  46 + <!--label: 'v333'-->
  47 + <!--},-->
  48 + <!--{-->
  49 + <!--value: 'v4',-->
  50 + <!--label: 'v4444'-->
  51 + <!--},-->
  52 + <!--{-->
  53 + <!--value: 'v5',-->
  54 + <!--label: 'v555'-->
  55 + <!--},-->
  56 + <!--{-->
  57 + <!--value: 'v6',-->
  58 + <!--label: 'v666'-->
  59 + <!--},-->
  60 + <!--{-->
  61 + <!--value: 'v7',-->
  62 + <!--label: 'v777'-->
  63 + <!--}-->
  64 + <!--]-->
  65 + <!--}]-->
  66 + <!--}-->
  67 + <!--],-->
  68 + <!--data3: [{-->
  69 + <!--value: 'beijing',-->
  70 + <!--label: '北京',-->
  71 + <!--children: [-->
  72 + <!--{-->
  73 + <!--value: 'gugong',-->
  74 + <!--label: '故宫'-->
  75 + <!--},-->
  76 + <!--{-->
  77 + <!--value: 'tiantan',-->
  78 + <!--label: '天坛'-->
  79 + <!--},-->
  80 + <!--{-->
  81 + <!--value: 'wangfujing',-->
  82 + <!--label: '王府井'-->
  83 + <!--}-->
  84 + <!--]-->
  85 + <!--}, {-->
  86 + <!--value: 'jiangsu',-->
  87 + <!--label: '江苏',-->
  88 + <!--children: [-->
  89 + <!--{-->
  90 + <!--value: 'nanjing',-->
  91 + <!--label: '南京',-->
  92 + <!--children: [-->
  93 + <!--{-->
  94 + <!--value: 'fuzimiao',-->
  95 + <!--label: '夫子庙',-->
  96 + <!--}-->
  97 + <!--]-->
  98 + <!--},-->
  99 + <!--{-->
  100 + <!--value: 'suzhou',-->
  101 + <!--label: '苏州',-->
  102 + <!--children: [-->
  103 + <!--{-->
  104 + <!--disabled: true,-->
  105 + <!--value: 'zhuozhengyuan',-->
  106 + <!--label: '拙政园',-->
  107 + <!--},-->
  108 + <!--{-->
  109 + <!--value: 'shizilin',-->
  110 + <!--label: '狮子林',-->
  111 + <!--}-->
  112 + <!--]-->
  113 + <!--}-->
  114 + <!--],-->
  115 + <!--}]-->
  116 + <!--}-->
  117 + <!--},-->
  118 + <!--methods: {-->
  119 + <!--handleLoad () {-->
  120 + <!--this.data2[0].loading = !this.data2[0].loading;-->
  121 + <!--},-->
  122 + <!--loadData (item, cb) {-->
  123 + <!--item.loading = true;-->
  124 + <!--setTimeout(() => {-->
  125 + <!--if (item.value === 'zhejiang') {-->
  126 + <!--item.children = [-->
  127 + <!--{-->
  128 + <!--value: 'hangzhou',-->
  129 + <!--label: '杭州',-->
  130 + <!--loading: false,-->
  131 + <!--children: []-->
  132 + <!--}-->
  133 + <!--];-->
  134 + <!--} else if (item.value === 'hangzhou') {-->
  135 + <!--item.children = [-->
  136 + <!--{-->
  137 + <!--value: 'ali',-->
  138 + <!--label: '阿里巴巴'-->
  139 + <!--}-->
  140 + <!--];-->
  141 + <!--}-->
  142 + <!--item.loading = false;-->
  143 + <!--cb();-->
  144 + <!--}, 1000);-->
  145 + <!--}-->
  146 + <!--}-->
  147 + <!--}-->
  148 +<!--</script>-->
  149 +
  150 +
1 <template> 151 <template>
2 - <Row>  
3 - <i-col span="4">  
4 - <Button @click="handleLoad">load</Button>  
5 - {{ v1 }}  
6 - </i-col>  
7 - <i-col span="4">  
8 - <Cascader :data="data2" filterable v-model="v1" style="width: 200px;"></Cascader>  
9 - <!--<Cascader :data="data2" filterable v-model="v1" :loadData="loadData"></Cascader>-->  
10 - </i-col>  
11 - </Row> 152 + <Cascader :data="data4" :load-data="loadData" style="width: 200px;"></Cascader>
12 </template> 153 </template>
13 <script> 154 <script>
14 export default { 155 export default {
15 data () { 156 data () {
16 return { 157 return {
17 - v1: [],  
18 - data2: [ 158 + data4: [
19 { 159 {
20 - value: 'zhejiang',  
21 - label: '浙江', 160 + value: 'beijing',
  161 + label: '北京',
22 children: [], 162 children: [],
23 loading: false 163 loading: false
24 }, 164 },
25 { 165 {
26 - value: 'jiangsu',  
27 - label: '江苏',  
28 - children: [{  
29 - value: 'nanjing',  
30 - label: '南京',  
31 - children: [  
32 - {  
33 - value: 'zhonghuamen',  
34 - label: '中华门'  
35 - },  
36 - {  
37 - value: 'v1',  
38 - label: 'v111'  
39 - },  
40 - {  
41 - value: 'v2',  
42 - label: 'v2222'  
43 - },  
44 - {  
45 - value: 'v3',  
46 - label: 'v333'  
47 - },  
48 - {  
49 - value: 'v4',  
50 - label: 'v4444'  
51 - },  
52 - {  
53 - value: 'v5',  
54 - label: 'v555'  
55 - },  
56 - {  
57 - value: 'v6',  
58 - label: 'v666'  
59 - },  
60 - {  
61 - value: 'v7',  
62 - label: 'v777'  
63 - }  
64 - ]  
65 - }] 166 + value: 'hangzhou',
  167 + label: '杭州',
  168 + children: [],
  169 + loading:false
66 } 170 }
67 - ],  
68 - data3: [{  
69 - value: 'beijing',  
70 - label: '北京',  
71 - children: [  
72 - {  
73 - value: 'gugong',  
74 - label: '故宫'  
75 - },  
76 - {  
77 - value: 'tiantan',  
78 - label: '天坛'  
79 - },  
80 - {  
81 - value: 'wangfujing',  
82 - label: '王府井'  
83 - }  
84 - ]  
85 - }, {  
86 - value: 'jiangsu',  
87 - label: '江苏',  
88 - children: [  
89 - {  
90 - value: 'nanjing',  
91 - label: '南京',  
92 - children: [  
93 - {  
94 - value: 'fuzimiao',  
95 - label: '夫子庙',  
96 - }  
97 - ]  
98 - },  
99 - {  
100 - value: 'suzhou',  
101 - label: '苏州',  
102 - children: [  
103 - {  
104 - disabled: true,  
105 - value: 'zhuozhengyuan',  
106 - label: '拙政园',  
107 - },  
108 - {  
109 - value: 'shizilin',  
110 - label: '狮子林',  
111 - }  
112 - ]  
113 - }  
114 - ],  
115 - }] 171 + ]
116 } 172 }
117 }, 173 },
118 methods: { 174 methods: {
119 - handleLoad () {  
120 - this.data2[0].loading = !this.data2[0].loading;  
121 - },  
122 - loadData (item, cb) { 175 + loadData (item, callback) {
123 item.loading = true; 176 item.loading = true;
124 setTimeout(() => { 177 setTimeout(() => {
125 - if (item.value === 'zhejiang') { 178 + if (item.value === 'beijing') {
126 item.children = [ 179 item.children = [
127 { 180 {
128 - value: 'hangzhou',  
129 - label: '杭州',  
130 - loading: false,  
131 - children: [] 181 + value: 'talkingdata',
  182 + label: 'TalkingData'
  183 + },
  184 + {
  185 + value: 'baidu',
  186 + label: '百度'
  187 + },
  188 + {
  189 + value: 'sina',
  190 + label: '新浪'
132 } 191 }
133 ]; 192 ];
134 } else if (item.value === 'hangzhou') { 193 } else if (item.value === 'hangzhou') {
@@ -136,11 +195,15 @@ @@ -136,11 +195,15 @@
136 { 195 {
137 value: 'ali', 196 value: 'ali',
138 label: '阿里巴巴' 197 label: '阿里巴巴'
  198 + },
  199 + {
  200 + value: '163',
  201 + label: '网易'
139 } 202 }
140 ]; 203 ];
141 } 204 }
142 item.loading = false; 205 item.loading = false;
143 - cb(); 206 + callback();
144 }, 1000); 207 }, 1000);
145 } 208 }
146 } 209 }
src/components/cascader/cascader.vue
@@ -128,7 +128,9 @@ @@ -128,7 +128,9 @@
128 tmpSelected: [], 128 tmpSelected: [],
129 updatingValue: false, // to fix set value in changeOnSelect type 129 updatingValue: false, // to fix set value in changeOnSelect type
130 currentValue: this.value, 130 currentValue: this.value,
131 - query: '' 131 + query: '',
  132 + validDataStr: '',
  133 + isLoadedChildren: false // #950
132 }; 134 };
133 }, 135 },
134 computed: { 136 computed: {
@@ -270,9 +272,31 @@ @@ -270,9 +272,31 @@
270 }, 272 },
271 handleFocus () { 273 handleFocus () {
272 this.$refs.input.focus(); 274 this.$refs.input.focus();
  275 + },
  276 + // 排除 loading 后的 data,避免重复触发 updateSelect
  277 + getValidData (data) {
  278 + function deleteData (item) {
  279 + const new_item = Object.assign({}, item);
  280 + if ('loading' in new_item) {
  281 + delete new_item.loading;
  282 + }
  283 + if ('__value' in new_item) {
  284 + delete new_item.__value;
  285 + }
  286 + if ('__label' in new_item) {
  287 + delete new_item.__label;
  288 + }
  289 + if ('children' in new_item && new_item.children.length) {
  290 + new_item.children = new_item.children.map(i => deleteData(i));
  291 + }
  292 + return new_item;
  293 + }
  294 +
  295 + return data.map(item => deleteData(item));
273 } 296 }
274 }, 297 },
275 created () { 298 created () {
  299 + this.validDataStr = JSON.stringify(this.getValidData(this.data));
276 this.$on('on-result-change', (params) => { 300 this.$on('on-result-change', (params) => {
277 // lastValue: is click the final val 301 // lastValue: is click the final val
278 // fromInit: is this emit from update value 302 // fromInit: is this emit from update value
@@ -332,7 +356,14 @@ @@ -332,7 +356,14 @@
332 data: { 356 data: {
333 deep: true, 357 deep: true,
334 handler () { 358 handler () {
335 - this.$nextTick(() => this.updateSelected()); 359 + const validDataStr = JSON.stringify(this.getValidData(this.data));
  360 + if (validDataStr !== this.validDataStr) {
  361 + this.validDataStr = validDataStr;
  362 + if (!this.isLoadedChildren) {
  363 + this.$nextTick(() => this.updateSelected());
  364 + }
  365 + this.isLoadedChildren = false;
  366 + }
336 } 367 }
337 } 368 }
338 } 369 }
src/components/cascader/caspanel.vue
@@ -61,6 +61,7 @@ @@ -61,6 +61,7 @@
61 const cascader = findComponentUpward(this, 'Cascader'); 61 const cascader = findComponentUpward(this, 'Cascader');
62 if (cascader && cascader.loadData) { 62 if (cascader && cascader.loadData) {
63 cascader.loadData(item, () => { 63 cascader.loadData(item, () => {
  64 + cascader.isLoadedChildren = true;
64 this.handleTriggerItem(item); 65 this.handleTriggerItem(item);
65 }); 66 });
66 return; 67 return;