Commit 1cc28460da006084bf218f88ac96055717f868d0
1 parent
37b6b7d9
Exists in
master
and in
3 other branches
feat: 优化Select组件
Showing
2 changed files
with
82 additions
and
88 deletions
Show diff stats
examples/views/docs/component/select.md
| @@ -246,10 +246,12 @@ export default { | @@ -246,10 +246,12 @@ export default { | ||
| 246 | console.log(val); | 246 | console.log(val); |
| 247 | return new Promise(resolve => { | 247 | return new Promise(resolve => { |
| 248 | setTimeout(() => { | 248 | setTimeout(() => { |
| 249 | - resolve([ | ||
| 250 | - { name: '王五', code: 'ww' }, | ||
| 251 | - { name: '赵六', code: 'zl' }, | ||
| 252 | - ]); | 249 | + resolve({ |
| 250 | + result: [ | ||
| 251 | + { name: '王五', code: 'ww' }, | ||
| 252 | + { name: '赵六', code: 'zl' }, | ||
| 253 | + ] | ||
| 254 | + }); | ||
| 253 | }, 1000); | 255 | }, 1000); |
| 254 | }); | 256 | }); |
| 255 | }, | 257 | }, |
| @@ -289,10 +291,12 @@ export default { | @@ -289,10 +291,12 @@ export default { | ||
| 289 | queryAPI(val) { | 291 | queryAPI(val) { |
| 290 | return new Promise(resolve => { | 292 | return new Promise(resolve => { |
| 291 | setTimeout(() => { | 293 | setTimeout(() => { |
| 292 | - resolve([ | ||
| 293 | - { name: '王五', code: 'ww' }, | ||
| 294 | - { name: '赵六', code: 'zl' }, | ||
| 295 | - ]); | 294 | + resolve({ |
| 295 | + result: [ | ||
| 296 | + { name: '王五', code: 'ww' }, | ||
| 297 | + { name: '赵六', code: 'zl' }, | ||
| 298 | + ] | ||
| 299 | + }); | ||
| 296 | }, 1000); | 300 | }, 1000); |
| 297 | }); | 301 | }); |
| 298 | }, | 302 | }, |
| @@ -309,7 +313,7 @@ export default { | @@ -309,7 +313,7 @@ export default { | ||
| 309 | <template> | 313 | <template> |
| 310 | <div> | 314 | <div> |
| 311 | <pre class="demo-model" v-if="model.length">{{ model }}</pre> | 315 | <pre class="demo-model" v-if="model.length">{{ model }}</pre> |
| 312 | - <z-select v-model="model" :queryApi="queryAPI" :options="options" multiple update></z-select> | 316 | + <z-select v-model="model" :queryApi="queryAPI" :options="options" multiple update raw></z-select> |
| 313 | </div> | 317 | </div> |
| 314 | </template> | 318 | </template> |
| 315 | 319 | ||
| @@ -317,7 +321,11 @@ export default { | @@ -317,7 +321,11 @@ export default { | ||
| 317 | export default { | 321 | export default { |
| 318 | data() { | 322 | data() { |
| 319 | return { | 323 | return { |
| 320 | - model: ['wq', 'cs'], | 324 | + // model: ['wq', 'cs'], |
| 325 | + model: [ | ||
| 326 | + { name: '王七', code: 'wq' }, | ||
| 327 | + { name: '陈拾', code: 'cs' }, | ||
| 328 | + ], | ||
| 321 | options: [ | 329 | options: [ |
| 322 | { name: '王七', code: 'wq' }, | 330 | { name: '王七', code: 'wq' }, |
| 323 | { name: '陈拾', code: 'cs' }, | 331 | { name: '陈拾', code: 'cs' }, |
| @@ -328,10 +336,12 @@ export default { | @@ -328,10 +336,12 @@ export default { | ||
| 328 | queryAPI(val) { | 336 | queryAPI(val) { |
| 329 | return new Promise(resolve => { | 337 | return new Promise(resolve => { |
| 330 | setTimeout(() => { | 338 | setTimeout(() => { |
| 331 | - resolve([ | ||
| 332 | - { name: '王五', code: 'ww' }, | ||
| 333 | - { name: '赵六', code: 'zl' }, | ||
| 334 | - ]); | 339 | + resolve({ |
| 340 | + result: [ | ||
| 341 | + { name: '王五', code: 'ww' }, | ||
| 342 | + { name: '赵六', code: 'zl' }, | ||
| 343 | + ] | ||
| 344 | + }); | ||
| 335 | }, 1000); | 345 | }, 1000); |
| 336 | }); | 346 | }); |
| 337 | }, | 347 | }, |
| @@ -369,12 +379,13 @@ export default { | @@ -369,12 +379,13 @@ export default { | ||
| 369 | methods: { | 379 | methods: { |
| 370 | queryAPI(val) { | 380 | queryAPI(val) { |
| 371 | return new Promise(resolve => { | 381 | return new Promise(resolve => { |
| 372 | - this.label = ''; | ||
| 373 | setTimeout(() => { | 382 | setTimeout(() => { |
| 374 | - resolve([ | ||
| 375 | - { name: '王五', code: 'ww' }, | ||
| 376 | - { name: '赵六', code: 'zl' }, | ||
| 377 | - ]); | 383 | + resolve({ |
| 384 | + result: [ | ||
| 385 | + { name: '王五', code: 'ww' }, | ||
| 386 | + { name: '赵六', code: 'zl' }, | ||
| 387 | + ] | ||
| 388 | + }); | ||
| 378 | }, 1000); | 389 | }, 1000); |
| 379 | }); | 390 | }); |
| 380 | }, | 391 | }, |
| @@ -410,10 +421,12 @@ export default { | @@ -410,10 +421,12 @@ export default { | ||
| 410 | queryAPI(val) { | 421 | queryAPI(val) { |
| 411 | return new Promise(resolve => { | 422 | return new Promise(resolve => { |
| 412 | setTimeout(() => { | 423 | setTimeout(() => { |
| 413 | - resolve([ | ||
| 414 | - { name: '王五', code: 'ww' }, | ||
| 415 | - { name: '赵六', code: 'zl' }, | ||
| 416 | - ]); | 424 | + resolve({ |
| 425 | + result: [ | ||
| 426 | + { name: '王五', code: 'ww' }, | ||
| 427 | + { name: '赵六', code: 'zl' }, | ||
| 428 | + ] | ||
| 429 | + }); | ||
| 417 | }, 1000); | 430 | }, 1000); |
| 418 | }); | 431 | }); |
| 419 | }, | 432 | }, |
| @@ -449,10 +462,12 @@ selectProps | Element Select组件参数 | Object | - | - | @@ -449,10 +462,12 @@ selectProps | Element Select组件参数 | Object | - | - | ||
| 449 | raw | 是否绑定原始对象 | Boolean | - | false | 462 | raw | 是否绑定原始对象 | Boolean | - | false |
| 450 | url | 远程搜索URL | String | - | - | 463 | url | 远程搜索URL | String | - | - |
| 451 | http | HTTP请求库 | Function | - | - | 464 | http | HTTP请求库 | Function | - | - |
| 465 | +params | 请求参数 | Object | - | {} | ||
| 452 | queryApi | 自定义接口 | Function | - | - | 466 | queryApi | 自定义接口 | Function | - | - |
| 453 | triggerSize | 触发远程搜索的字段长度 | Number | - | 0 | 467 | triggerSize | 触发远程搜索的字段长度 | Number | - | 0 |
| 454 | -auto | 初始化时自动查询数据 | Boolean | - | false | 468 | +auto | 初始化时自动查询数据 | Boolean | - | true |
| 455 | update | 点开下拉框时更新数据 | Boolean | - | false | 469 | update | 点开下拉框时更新数据 | Boolean | - | false |
| 470 | +update-once | 点开下拉框时更新一次数据 | Boolean | - | false | ||
| 456 | 471 | ||
| 457 | ## Events 事件 | 472 | ## Events 事件 |
| 458 | 473 |
packages/select/index.vue
| @@ -81,6 +81,16 @@ export default { | @@ -81,6 +81,16 @@ export default { | ||
| 81 | url: String, | 81 | url: String, |
| 82 | // HTTP请求库 | 82 | // HTTP请求库 |
| 83 | http: Function, | 83 | http: Function, |
| 84 | + // 请求参数 | ||
| 85 | + params: { | ||
| 86 | + type: Object, | ||
| 87 | + default: () => ({}), | ||
| 88 | + }, | ||
| 89 | + // 请求配置 | ||
| 90 | + config: { | ||
| 91 | + type: Object, | ||
| 92 | + default: () => ({}), | ||
| 93 | + }, | ||
| 84 | // 自定义接口 | 94 | // 自定义接口 |
| 85 | queryApi: Function, | 95 | queryApi: Function, |
| 86 | // 触发远程搜索的字段长度 | 96 | // 触发远程搜索的字段长度 |
| @@ -88,8 +98,12 @@ export default { | @@ -88,8 +98,12 @@ export default { | ||
| 88 | type: Number, | 98 | type: Number, |
| 89 | default: 0, | 99 | default: 0, |
| 90 | }, | 100 | }, |
| 91 | - auto: Boolean, | 101 | + auto: { |
| 102 | + type: Boolean, | ||
| 103 | + default: true, | ||
| 104 | + }, | ||
| 92 | update: Boolean, | 105 | update: Boolean, |
| 106 | + updateOnce: Boolean, | ||
| 93 | }, | 107 | }, |
| 94 | data() { | 108 | data() { |
| 95 | return { | 109 | return { |
| @@ -98,6 +112,7 @@ export default { | @@ -98,6 +112,7 @@ export default { | ||
| 98 | optionsCurrent: this.fixOptions(this.options), | 112 | optionsCurrent: this.fixOptions(this.options), |
| 99 | loading: false, | 113 | loading: false, |
| 100 | initing: false, | 114 | initing: false, |
| 115 | + loaded: false, | ||
| 101 | }; | 116 | }; |
| 102 | }, | 117 | }, |
| 103 | created() { | 118 | created() { |
| @@ -144,8 +159,14 @@ export default { | @@ -144,8 +159,14 @@ export default { | ||
| 144 | return { | 159 | return { |
| 145 | ..._events, | 160 | ..._events, |
| 146 | 'visible-change': show => { | 161 | 'visible-change': show => { |
| 147 | - if (this.remote && this.update && show) { | ||
| 148 | - this.remoteMethod(); | 162 | + if (this.remote && show) { |
| 163 | + if (this.updateOnce) { | ||
| 164 | + if (!this.loaded) { | ||
| 165 | + this.remoteMethod(); | ||
| 166 | + } | ||
| 167 | + } else if (this.update) { | ||
| 168 | + this.remoteMethod(); | ||
| 169 | + } | ||
| 149 | } | 170 | } |
| 150 | _events['visible-change'] && _events['visible-change'](show); | 171 | _events['visible-change'] && _events['visible-change'](show); |
| 151 | }, | 172 | }, |
| @@ -155,64 +176,24 @@ export default { | @@ -155,64 +176,24 @@ export default { | ||
| 155 | methods: { | 176 | methods: { |
| 156 | // 修复当前数据源包含当前选中项 | 177 | // 修复当前数据源包含当前选中项 |
| 157 | fixOptions(list) { | 178 | fixOptions(list) { |
| 158 | - if (!this.value || (this.value instanceof Array && this.value.length === 0) || (this.value instanceof Object && Object.keys(this.value).length === 0)) { | ||
| 159 | - return list; | ||
| 160 | - } | 179 | + let fixOptions = []; |
| 161 | if (this.raw) { | 180 | if (this.raw) { |
| 162 | - // 绑定为对象值时修复默认项 | ||
| 163 | - let fixOptions = []; | ||
| 164 | - let defaultOptions = []; | ||
| 165 | if (this.multiple) { | 181 | if (this.multiple) { |
| 166 | - fixOptions = [...this.value]; | ||
| 167 | - this.options.forEach(item => { | ||
| 168 | - if (this.value.find(i => i[this.valueKey] === item[this.valueKey])) { | ||
| 169 | - defaultOptions.push(item); | ||
| 170 | - } | ||
| 171 | - }); | 182 | + fixOptions = this.value && this.value.length > 0 ? [...this.value] : []; |
| 172 | } else { | 183 | } else { |
| 173 | - fixOptions = [this.value]; | ||
| 174 | - this.options.forEach(item => { | ||
| 175 | - if (item[this.valueKey] === this.value[this.valueKey]) { | ||
| 176 | - defaultOptions.push(item); | ||
| 177 | - } | ||
| 178 | - }); | 184 | + fixOptions = this.value && Object.keys(this.value).length > 0 ? [this.value] : []; |
| 179 | } | 185 | } |
| 180 | - let hash = {}; | ||
| 181 | - const options = [...fixOptions, ...defaultOptions, ...list].reduce((result, item) => { | ||
| 182 | - if (!hash[item[this.valueKey]]) { | ||
| 183 | - // 如果当前元素的key值没有在hash对象里,则可放入最终结果数组 | ||
| 184 | - hash[item[this.valueKey]] = true; // 把当前元素key值添加到hash对象 | ||
| 185 | - result.push(item); // 把当前元素放入结果数组 | ||
| 186 | - } | ||
| 187 | - return result; // 返回结果数组 | ||
| 188 | - }, []); | ||
| 189 | - return options; | ||
| 190 | - } else { | ||
| 191 | - // 绑定为非对象值时修复默认项 | ||
| 192 | - let defaultOptions = []; | ||
| 193 | - if (this.multiple) { | ||
| 194 | - this.options.forEach(item => { | ||
| 195 | - if (this.value.find(i => i === item[this.valueKey])) { | ||
| 196 | - defaultOptions.push(item); | ||
| 197 | - } | ||
| 198 | - }); | ||
| 199 | - } else { | ||
| 200 | - const targetOption = this.options.find(item => item[this.valueKey] === this.value); | ||
| 201 | - if (targetOption) { | ||
| 202 | - defaultOptions = [targetOption]; | ||
| 203 | - } | ||
| 204 | - } | ||
| 205 | - let hash = {}; | ||
| 206 | - const options = [...defaultOptions, ...list].reduce((result, item) => { | ||
| 207 | - if (!hash[item[this.valueKey]]) { | ||
| 208 | - // 如果当前元素的key值没有在hash对象里,则可放入最终结果数组 | ||
| 209 | - hash[item[this.valueKey]] = true; // 把当前元素key值添加到hash对象 | ||
| 210 | - result.push(item); // 把当前元素放入结果数组 | ||
| 211 | - } | ||
| 212 | - return result; // 返回结果数组 | ||
| 213 | - }, []); | ||
| 214 | - return options; | ||
| 215 | } | 186 | } |
| 187 | + let hash = {}; | ||
| 188 | + const options = [...fixOptions, ...this.options, ...list].reduce((result, item) => { | ||
| 189 | + if (!hash[item[this.valueKey]]) { | ||
| 190 | + // 如果当前元素的key值没有在hash对象里,则可放入最终结果数组 | ||
| 191 | + hash[item[this.valueKey]] = true; // 把当前元素key值添加到hash对象 | ||
| 192 | + item[this.valueKey] && item[this.labelKey] && result.push(item); // 把当前元素放入结果数组 | ||
| 193 | + } | ||
| 194 | + return result; // 返回结果数组 | ||
| 195 | + }, []); | ||
| 196 | + return options; | ||
| 216 | }, | 197 | }, |
| 217 | // 远程加载 | 198 | // 远程加载 |
| 218 | remoteMethod(val = '') { | 199 | remoteMethod(val = '') { |
| @@ -226,23 +207,21 @@ export default { | @@ -226,23 +207,21 @@ export default { | ||
| 226 | requestPrimise = this.request({ | 207 | requestPrimise = this.request({ |
| 227 | url: this.url, | 208 | url: this.url, |
| 228 | method: 'get', | 209 | method: 'get', |
| 229 | - params: searchText ? { [this.searchKey]: searchText } : {}, | 210 | + params: searchText ? { [this.searchKey]: searchText, ...this.params } : this.params, |
| 211 | + ...this.config, | ||
| 230 | }); | 212 | }); |
| 231 | } | 213 | } |
| 232 | requestPrimise | 214 | requestPrimise |
| 233 | - .then(list => { | ||
| 234 | - const options = this.fixOptions(list); | 215 | + .then(res => { |
| 216 | + const response = res || {}; | ||
| 217 | + const options = this.fixOptions(response.result); | ||
| 235 | this.optionsDataSource = options; | 218 | this.optionsDataSource = options; |
| 236 | this.optionsCurrent = options; | 219 | this.optionsCurrent = options; |
| 237 | - // 获取到选项数据源时刷新绑定显示值 | ||
| 238 | - this.model = undefined; | ||
| 239 | - this.$nextTick(() => { | ||
| 240 | - this.model = this.value; | ||
| 241 | - }); | ||
| 242 | }) | 220 | }) |
| 243 | .finally(() => { | 221 | .finally(() => { |
| 244 | this.loading = false; | 222 | this.loading = false; |
| 245 | this.initing = false; | 223 | this.initing = false; |
| 224 | + this.loaded = true; | ||
| 246 | }); | 225 | }); |
| 247 | } else { | 226 | } else { |
| 248 | this.optionsCurrent = this.optionsDataSource.filter(item => { | 227 | this.optionsCurrent = this.optionsDataSource.filter(item => { |