fix(runtime-core): ensure inhertied attrs update on optimized child root

fix #677, close #784
This commit is contained in:
Evan You 2020-02-27 21:51:57 -05:00
parent 33ab0f8e0f
commit 6810d1402e
2 changed files with 41 additions and 2 deletions

View File

@ -6,7 +6,9 @@ import {
mergeProps,
ref,
onUpdated,
defineComponent
defineComponent,
openBlock,
createBlock
} from '@vue/runtime-dom'
import { mockWarn } from '@vue/shared'
@ -346,4 +348,36 @@ describe('attribute fallthrough', () => {
expect(`Extraneous non-props attributes`).not.toHaveBeenWarned()
expect(root.innerHTML).toBe(`<div></div><div class="parent"></div>`)
})
// #677
it('should update merged dynamic attrs on optimized child root', async () => {
const id = ref('foo')
const cls = ref('bar')
const Parent = {
render() {
return h(Child, { id: id.value, class: cls.value })
}
}
const Child = {
props: [],
render() {
return openBlock(), createBlock('div')
}
}
const root = document.createElement('div')
document.body.appendChild(root)
render(h(Parent), root)
expect(root.innerHTML).toBe(`<div id="foo" class="bar"></div>`)
id.value = 'fooo'
await nextTick()
expect(root.innerHTML).toBe(`<div id="fooo" class="bar"></div>`)
cls.value = 'barr'
await nextTick()
expect(root.innerHTML).toBe(`<div id="fooo" class="barr"></div>`)
})
})

View File

@ -90,6 +90,11 @@ export function renderComponentRoot(
result.shapeFlag & ShapeFlags.COMPONENT
) {
result = cloneVNode(result, attrs)
// If the child root node is a compiler optimized vnode, make sure it
// force update full props to account for the merged attrs.
if (result.dynamicChildren !== null) {
result.patchFlag |= PatchFlags.FULL_PROPS
}
} else if (__DEV__ && !accessedAttrs && result.type !== Comment) {
warn(
`Extraneous non-props attributes (${Object.keys(attrs).join(',')}) ` +
@ -183,7 +188,7 @@ export function shouldUpdateComponent(
return hasPropsChanged(prevProps!, nextProps!)
} else {
if (patchFlag & PatchFlags.CLASS) {
return prevProps!.class === nextProps!.class
return prevProps!.class !== nextProps!.class
}
if (patchFlag & PatchFlags.STYLE) {
return hasPropsChanged(prevProps!.style, nextProps!.style)