mirror of https://github.com/vuejs/vue.git
				
				
				
			warn non-Array value for <select multiple> (close #3191)
This commit is contained in:
		
							parent
							
								
									41a3b79ecd
								
							
						
					
					
						commit
						5b668a9222
					
				|  | @ -32,7 +32,7 @@ export default { | |||
|       } | ||||
|     } | ||||
|     if (vnode.tag === 'select') { | ||||
|       setSelected(el, binding.value) | ||||
|       setSelected(el, binding, vnode.context) | ||||
|     } else { | ||||
|       if (!isAndroid) { | ||||
|         el.addEventListener('compositionstart', onCompositionStart) | ||||
|  | @ -45,16 +45,15 @@ export default { | |||
|     } | ||||
|   }, | ||||
|   componentUpdated (el, binding, vnode) { | ||||
|     const val = binding.value | ||||
|     if (vnode.tag === 'select') { | ||||
|       setSelected(el, val) | ||||
|       setSelected(el, binding, vnode.context) | ||||
|       // in case the options rendered by v-for have changed,
 | ||||
|       // it's possible that the value is out-of-sync with the rendered options.
 | ||||
|       // detect such cases and filter out values that no longer has a matchig
 | ||||
|       // option in the DOM.
 | ||||
|       const needReset = el.multiple | ||||
|         ? val.some(v => hasNoMatchingOption(v, el.options)) | ||||
|         : hasNoMatchingOption(val, el.options) | ||||
|         ? binding.value.some(v => hasNoMatchingOption(v, el.options)) | ||||
|         : hasNoMatchingOption(binding.value, el.options) | ||||
|       if (needReset) { | ||||
|         trigger(el, 'change') | ||||
|       } | ||||
|  | @ -62,10 +61,20 @@ export default { | |||
|   } | ||||
| } | ||||
| 
 | ||||
| function setSelected (el, value) { | ||||
| function setSelected (el, binding, vm) { | ||||
|   const value = binding.value | ||||
|   const isMultiple = el.multiple | ||||
|   if (!isMultiple) { | ||||
|     el.selectedIndex = -1 | ||||
|   } else if (!Array.isArray(value)) { | ||||
|     process.env.NODE_ENV !== 'production' && warn( | ||||
|       `<select multiple v-model="${binding.expression}"> ` + | ||||
|       `expects an Array value for its binding, but got ${ | ||||
|         Object.prototype.toString.call(value).slice(8, -1) | ||||
|       }`,
 | ||||
|       vm | ||||
|     ) | ||||
|     return | ||||
|   } | ||||
|   for (let i = 0, l = el.options.length; i < l; i++) { | ||||
|     const option = el.options[i] | ||||
|  |  | |||
|  | @ -203,4 +203,16 @@ describe('Directive v-model select', () => { | |||
|     expect('inline selected attributes on <option> will be ignored when using v-model') | ||||
|       .toHaveBeenWarned() | ||||
|   }) | ||||
| 
 | ||||
|   it('should warn multiple with non-Array value', () => { | ||||
|     const vm = new Vue({ | ||||
|       data: { | ||||
|         test: 'meh' | ||||
|       }, | ||||
|       template: | ||||
|         '<select v-model="test" multiple></select>' | ||||
|     }).$mount() | ||||
|     expect('<select multiple v-model="test"> expects an Array value for its binding, but got String') | ||||
|       .toHaveBeenWarned() | ||||
|   }) | ||||
| }) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue