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 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 153 </template>
13 154 <script>
14 155 export default {
15 156 data () {
16 157 return {
17   - v1: [],
18   - data2: [
  158 + data4: [
19 159 {
20   - value: 'zhejiang',
21   - label: '浙江',
  160 + value: 'beijing',
  161 + label: '北京',
22 162 children: [],
23 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 174 methods: {
119   - handleLoad () {
120   - this.data2[0].loading = !this.data2[0].loading;
121   - },
122   - loadData (item, cb) {
  175 + loadData (item, callback) {
123 176 item.loading = true;
124 177 setTimeout(() => {
125   - if (item.value === 'zhejiang') {
  178 + if (item.value === 'beijing') {
126 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 193 } else if (item.value === 'hangzhou') {
... ... @@ -136,11 +195,15 @@
136 195 {
137 196 value: 'ali',
138 197 label: '阿里巴巴'
  198 + },
  199 + {
  200 + value: '163',
  201 + label: '网易'
139 202 }
140 203 ];
141 204 }
142 205 item.loading = false;
143   - cb();
  206 + callback();
144 207 }, 1000);
145 208 }
146 209 }
... ...
src/components/cascader/cascader.vue
... ... @@ -128,7 +128,9 @@
128 128 tmpSelected: [],
129 129 updatingValue: false, // to fix set value in changeOnSelect type
130 130 currentValue: this.value,
131   - query: ''
  131 + query: '',
  132 + validDataStr: '',
  133 + isLoadedChildren: false // #950
132 134 };
133 135 },
134 136 computed: {
... ... @@ -270,9 +272,31 @@
270 272 },
271 273 handleFocus () {
272 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 298 created () {
  299 + this.validDataStr = JSON.stringify(this.getValidData(this.data));
276 300 this.$on('on-result-change', (params) => {
277 301 // lastValue: is click the final val
278 302 // fromInit: is this emit from update value
... ... @@ -332,7 +356,14 @@
332 356 data: {
333 357 deep: true,
334 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 61 const cascader = findComponentUpward(this, 'Cascader');
62 62 if (cascader && cascader.loadData) {
63 63 cascader.loadData(item, () => {
  64 + cascader.isLoadedChildren = true;
64 65 this.handleTriggerItem(item);
65 66 });
66 67 return;
... ...