fix(defineModel): detect changes respect custom getter and setter (#11543)

fix: #11541
fix: #11526
close: #11527
This commit is contained in:
LiuSeen 2024-08-07 22:10:01 +08:00 committed by GitHub
parent b1abac06cd
commit e0428884b5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 95 additions and 2 deletions

View File

@ -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)
})
})

View File

@ -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