fix(v-model): avoid mutation when using Set models + fix multi select Set model update
This commit is contained in:
		
							parent
							
								
									83a79a829c
								
							
						
					
					
						commit
						f2b0a8e81d
					
				@ -884,18 +884,21 @@ describe('vModel', () => {
 | 
				
			|||||||
    foo.selected = true
 | 
					    foo.selected = true
 | 
				
			||||||
    triggerEvent('change', input)
 | 
					    triggerEvent('change', input)
 | 
				
			||||||
    await nextTick()
 | 
					    await nextTick()
 | 
				
			||||||
 | 
					    expect(data.value).toBeInstanceOf(Set)
 | 
				
			||||||
    expect(data.value).toMatchObject(new Set(['foo']))
 | 
					    expect(data.value).toMatchObject(new Set(['foo']))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    foo.selected = false
 | 
					    foo.selected = false
 | 
				
			||||||
    bar.selected = true
 | 
					    bar.selected = true
 | 
				
			||||||
    triggerEvent('change', input)
 | 
					    triggerEvent('change', input)
 | 
				
			||||||
    await nextTick()
 | 
					    await nextTick()
 | 
				
			||||||
 | 
					    expect(data.value).toBeInstanceOf(Set)
 | 
				
			||||||
    expect(data.value).toMatchObject(new Set(['bar']))
 | 
					    expect(data.value).toMatchObject(new Set(['bar']))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    foo.selected = true
 | 
					    foo.selected = true
 | 
				
			||||||
    bar.selected = true
 | 
					    bar.selected = true
 | 
				
			||||||
    triggerEvent('change', input)
 | 
					    triggerEvent('change', input)
 | 
				
			||||||
    await nextTick()
 | 
					    await nextTick()
 | 
				
			||||||
 | 
					    expect(data.value).toBeInstanceOf(Set)
 | 
				
			||||||
    expect(data.value).toMatchObject(new Set(['foo', 'bar']))
 | 
					    expect(data.value).toMatchObject(new Set(['foo', 'bar']))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    foo.selected = false
 | 
					    foo.selected = false
 | 
				
			||||||
 | 
				
			|||||||
@ -118,11 +118,13 @@ export const vModelCheckbox: ModelDirective<HTMLInputElement> = {
 | 
				
			|||||||
          assign(filtered)
 | 
					          assign(filtered)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      } else if (isSet(modelValue)) {
 | 
					      } else if (isSet(modelValue)) {
 | 
				
			||||||
 | 
					        const cloned = new Set(modelValue)
 | 
				
			||||||
        if (checked) {
 | 
					        if (checked) {
 | 
				
			||||||
          modelValue.add(elementValue)
 | 
					          cloned.add(elementValue)
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          modelValue.delete(elementValue)
 | 
					          cloned.delete(elementValue)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        assign(cloned)
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        assign(getCheckboxValue(el, checked))
 | 
					        assign(getCheckboxValue(el, checked))
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -168,7 +170,8 @@ export const vModelRadio: ModelDirective<HTMLInputElement> = {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const vModelSelect: ModelDirective<HTMLSelectElement> = {
 | 
					export const vModelSelect: ModelDirective<HTMLSelectElement> = {
 | 
				
			||||||
  created(el, { modifiers: { number } }, vnode) {
 | 
					  created(el, { value, modifiers: { number } }, vnode) {
 | 
				
			||||||
 | 
					    const isSetModel = isSet(value)
 | 
				
			||||||
    addEventListener(el, 'change', () => {
 | 
					    addEventListener(el, 'change', () => {
 | 
				
			||||||
      const selectedVal = Array.prototype.filter
 | 
					      const selectedVal = Array.prototype.filter
 | 
				
			||||||
        .call(el.options, (o: HTMLOptionElement) => o.selected)
 | 
					        .call(el.options, (o: HTMLOptionElement) => o.selected)
 | 
				
			||||||
@ -176,7 +179,13 @@ export const vModelSelect: ModelDirective<HTMLSelectElement> = {
 | 
				
			|||||||
          (o: HTMLOptionElement) =>
 | 
					          (o: HTMLOptionElement) =>
 | 
				
			||||||
            number ? toNumber(getValue(o)) : getValue(o)
 | 
					            number ? toNumber(getValue(o)) : getValue(o)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
      el._assign(el.multiple ? selectedVal : selectedVal[0])
 | 
					      el._assign(
 | 
				
			||||||
 | 
					        el.multiple
 | 
				
			||||||
 | 
					          ? isSetModel
 | 
				
			||||||
 | 
					            ? new Set(selectedVal)
 | 
				
			||||||
 | 
					            : selectedVal
 | 
				
			||||||
 | 
					          : selectedVal[0]
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    el._assign = getModelAssigner(vnode)
 | 
					    el._assign = getModelAssigner(vnode)
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user