mergeProps,
ref,
onUpdated,
- defineComponent
+ defineComponent,
+ openBlock,
+ createBlock
} from '@vue/runtime-dom'
import { mockWarn } from '@vue/shared'
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>`)
+ })
})
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(',')}) ` +
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)