fix(runtime-core): separate null vs. non-null ref value updates (#1835)
fix #1789, fix #1834
This commit is contained in:
parent
b14f4a505b
commit
3991ff03ce
@ -268,4 +268,61 @@ describe('api: template refs', () => {
|
|||||||
// ref should be updated
|
// ref should be updated
|
||||||
expect(serializeInner(root)).toBe(`<div id="foo">foo</div>`)
|
expect(serializeInner(root)).toBe(`<div id="foo">foo</div>`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #1834
|
||||||
|
test('exchange refs', async () => {
|
||||||
|
const refToggle = ref(false)
|
||||||
|
const spy = jest.fn()
|
||||||
|
|
||||||
|
const Comp = {
|
||||||
|
render(this: any) {
|
||||||
|
return [
|
||||||
|
h('p', { ref: refToggle.value ? 'foo' : 'bar' }),
|
||||||
|
h('i', { ref: refToggle.value ? 'bar' : 'foo' })
|
||||||
|
]
|
||||||
|
},
|
||||||
|
mounted(this: any) {
|
||||||
|
spy(this.$refs.foo.tag, this.$refs.bar.tag)
|
||||||
|
},
|
||||||
|
updated(this: any) {
|
||||||
|
spy(this.$refs.foo.tag, this.$refs.bar.tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = nodeOps.createElement('div')
|
||||||
|
render(h(Comp), root)
|
||||||
|
|
||||||
|
expect(spy.mock.calls[0][0]).toBe('i')
|
||||||
|
expect(spy.mock.calls[0][1]).toBe('p')
|
||||||
|
refToggle.value = true
|
||||||
|
await nextTick()
|
||||||
|
expect(spy.mock.calls[1][0]).toBe('p')
|
||||||
|
expect(spy.mock.calls[1][1]).toBe('i')
|
||||||
|
})
|
||||||
|
|
||||||
|
// #1789
|
||||||
|
test('toggle the same ref to different elements', async () => {
|
||||||
|
const refToggle = ref(false)
|
||||||
|
const spy = jest.fn()
|
||||||
|
|
||||||
|
const Comp = {
|
||||||
|
render(this: any) {
|
||||||
|
return refToggle.value ? h('p', { ref: 'foo' }) : h('i', { ref: 'foo' })
|
||||||
|
},
|
||||||
|
mounted(this: any) {
|
||||||
|
spy(this.$refs.foo.tag)
|
||||||
|
},
|
||||||
|
updated(this: any) {
|
||||||
|
spy(this.$refs.foo.tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = nodeOps.createElement('div')
|
||||||
|
render(h(Comp), root)
|
||||||
|
|
||||||
|
expect(spy.mock.calls[0][0]).toBe('i')
|
||||||
|
refToggle.value = true
|
||||||
|
await nextTick()
|
||||||
|
expect(spy.mock.calls[1][0]).toBe('p')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -319,14 +319,28 @@ export const setRef = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isString(ref)) {
|
if (isString(ref)) {
|
||||||
refs[ref] = value
|
const doSet = () => {
|
||||||
if (hasOwn(setupState, ref)) {
|
refs[ref] = value
|
||||||
queuePostRenderEffect(() => {
|
if (hasOwn(setupState, ref)) {
|
||||||
setupState[ref] = value
|
setupState[ref] = value
|
||||||
}, parentSuspense)
|
}
|
||||||
|
}
|
||||||
|
// #1789: for non-null values, set them after render
|
||||||
|
// null values means this is unmount and it should not overwrite another
|
||||||
|
// ref with the same key
|
||||||
|
if (value) {
|
||||||
|
queuePostRenderEffect(doSet, parentSuspense)
|
||||||
|
} else {
|
||||||
|
doSet()
|
||||||
}
|
}
|
||||||
} else if (isRef(ref)) {
|
} else if (isRef(ref)) {
|
||||||
ref.value = value
|
if (value) {
|
||||||
|
queuePostRenderEffect(() => {
|
||||||
|
ref.value = value
|
||||||
|
}, parentSuspense)
|
||||||
|
} else {
|
||||||
|
ref.value = value
|
||||||
|
}
|
||||||
} else if (isFunction(ref)) {
|
} else if (isFunction(ref)) {
|
||||||
callWithErrorHandling(ref, parentComponent, ErrorCodes.FUNCTION_REF, [
|
callWithErrorHandling(ref, parentComponent, ErrorCodes.FUNCTION_REF, [
|
||||||
value,
|
value,
|
||||||
|
Loading…
Reference in New Issue
Block a user