mirror of https://github.com/vuejs/core.git
fix(defineModel): detect changes respect custom getter and setter (#11543)
fix: #11541 fix: #11526 close: #11527
This commit is contained in:
parent
b1abac06cd
commit
e0428884b5
|
@ -657,4 +657,96 @@ describe('useModel', () => {
|
|||
expect(setValue).toBeCalledTimes(2)
|
||||
expect(msg.value).toBe(defaultVal)
|
||||
})
|
||||
|
||||
// #11526
|
||||
test('custom getter', () => {
|
||||
let changeChildMsg!: (val: boolean) => void
|
||||
const getter = (value: boolean) => !value
|
||||
|
||||
const Comp = defineComponent({
|
||||
props: ['msg'],
|
||||
emits: ['update:msg'],
|
||||
setup(props) {
|
||||
const childMsg = useModel(props, 'msg', {
|
||||
get: getter,
|
||||
set: value => !value,
|
||||
})
|
||||
changeChildMsg = (val: boolean) => (childMsg.value = val)
|
||||
return () => {
|
||||
return childMsg.value
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const defaultVal = false
|
||||
const msg = ref(defaultVal)
|
||||
const Parent = defineComponent({
|
||||
setup() {
|
||||
return () =>
|
||||
h(Comp, {
|
||||
msg: msg.value,
|
||||
'onUpdate:msg': val => {
|
||||
msg.value = val
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
const root = nodeOps.createElement('div')
|
||||
render(h(Parent), root)
|
||||
|
||||
changeChildMsg(!getter(msg.value))
|
||||
expect(msg.value).toBe(true)
|
||||
|
||||
changeChildMsg(!getter(msg.value))
|
||||
expect(msg.value).toBe(false)
|
||||
})
|
||||
|
||||
// #11541
|
||||
test('custom setter', () => {
|
||||
let changeChildMsg!: (val: boolean) => void
|
||||
|
||||
const Comp = defineComponent({
|
||||
props: ['msg'],
|
||||
emits: ['update:msg'],
|
||||
setup(props) {
|
||||
const childMsg = useModel(props, 'msg', {
|
||||
set: value => {
|
||||
if (value === msg.value) {
|
||||
return null
|
||||
} else {
|
||||
return value
|
||||
}
|
||||
},
|
||||
})
|
||||
changeChildMsg = (val: boolean) => (childMsg.value = val)
|
||||
return () => {
|
||||
return childMsg.value
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const defaultVal = false
|
||||
const msg = ref(defaultVal)
|
||||
const Parent = defineComponent({
|
||||
setup() {
|
||||
return () =>
|
||||
h(Comp, {
|
||||
msg: msg.value,
|
||||
'onUpdate:msg': val => {
|
||||
msg.value = val
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
const root = nodeOps.createElement('div')
|
||||
render(h(Parent), root)
|
||||
|
||||
changeChildMsg(true)
|
||||
expect(msg.value).toBe(true)
|
||||
|
||||
changeChildMsg(true)
|
||||
expect(msg.value).toBe(null)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -51,8 +51,9 @@ export function useModel(
|
|||
},
|
||||
|
||||
set(value) {
|
||||
const emittedValue = options.set ? options.set(value) : value
|
||||
if (
|
||||
!hasChanged(value, localValue) &&
|
||||
!hasChanged(emittedValue, localValue) &&
|
||||
!(prevSetValue !== EMPTY_OBJ && hasChanged(value, prevSetValue))
|
||||
) {
|
||||
return
|
||||
|
@ -74,7 +75,7 @@ export function useModel(
|
|||
localValue = value
|
||||
trigger()
|
||||
}
|
||||
const emittedValue = options.set ? options.set(value) : value
|
||||
|
||||
i.emit(`update:${name}`, emittedValue)
|
||||
// #10279: if the local value is converted via a setter but the value
|
||||
// emitted to parent was the same, the parent will not trigger any
|
||||
|
|
Loading…
Reference in New Issue