prevValue: any,
nextValue: any,
namespace?: ElementNamespace,
- prevChildren?: VNode<HostNode, HostElement>[],
parentComponent?: ComponentInternalInstance | null,
- parentSuspense?: SuspenseBoundary | null,
- unmountChildren?: UnmountChildrenFn,
): void
insert(el: HostNode, parent: HostElement, anchor?: HostNode | null): void
remove(el: HostNode): void
if (props) {
for (const key in props) {
if (key !== 'value' && !isReservedProp(key)) {
- hostPatchProp(
- el,
- key,
- null,
- props[key],
- namespace,
- vnode.children as VNode[],
- parentComponent,
- parentSuspense,
- unmountChildren,
- )
+ hostPatchProp(el, key, null, props[key], namespace, parentComponent)
}
}
/**
dynamicChildren = null
}
+ // #9135 innerHTML / textContent unset needs to happen before possible
+ // new children mount
+ if (
+ (oldProps.innerHTML && newProps.innerHTML == null) ||
+ (oldProps.textContent && newProps.textContent == null)
+ ) {
+ hostSetElementText(el, '')
+ }
+
if (dynamicChildren) {
patchBlockChildren(
n1.dynamicChildren!,
// (i.e. at the exact same position in the source template)
if (patchFlag & PatchFlags.FULL_PROPS) {
// element props contain dynamic keys, full diff needed
- patchProps(
- el,
- n2,
- oldProps,
- newProps,
- parentComponent,
- parentSuspense,
- namespace,
- )
+ patchProps(el, oldProps, newProps, parentComponent, namespace)
} else {
// class
// this flag is matched when the element has dynamic class bindings.
const next = newProps[key]
// #1471 force patch value
if (next !== prev || key === 'value') {
- hostPatchProp(
- el,
- key,
- prev,
- next,
- namespace,
- n1.children as VNode[],
- parentComponent,
- parentSuspense,
- unmountChildren,
- )
+ hostPatchProp(el, key, prev, next, namespace, parentComponent)
}
}
}
}
} else if (!optimized && dynamicChildren == null) {
// unoptimized, full diff
- patchProps(
- el,
- n2,
- oldProps,
- newProps,
- parentComponent,
- parentSuspense,
- namespace,
- )
+ patchProps(el, oldProps, newProps, parentComponent, namespace)
}
if ((vnodeHook = newProps.onVnodeUpdated) || dirs) {
const patchProps = (
el: RendererElement,
- vnode: VNode,
oldProps: Data,
newProps: Data,
parentComponent: ComponentInternalInstance | null,
- parentSuspense: SuspenseBoundary | null,
namespace: ElementNamespace,
) => {
if (oldProps !== newProps) {
oldProps[key],
null,
namespace,
- vnode.children as VNode[],
parentComponent,
- parentSuspense,
- unmountChildren,
)
}
}
const prev = oldProps[key]
// defer patching value
if (next !== prev && key !== 'value') {
- hostPatchProp(
- el,
- key,
- prev,
- next,
- namespace,
- vnode.children as VNode[],
- parentComponent,
- parentSuspense,
- unmountChildren,
- )
+ hostPatchProp(el, key, prev, next, namespace, parentComponent)
}
}
if ('value' in newProps) {
import { patchProp } from '../src/patchProp'
-import { h, render } from '../src'
+import { h, nextTick, ref, render } from '../src'
describe('runtime-dom: props patching', () => {
test('basic', () => {
expect(fn).toHaveBeenCalled()
})
+ test('patch innerHTML porp', async () => {
+ const root = document.createElement('div')
+ const state = ref(false)
+ const Comp = {
+ render: () => {
+ if (state.value) {
+ return h('div', [h('del', null, 'baz')])
+ } else {
+ return h('div', { innerHTML: 'baz' })
+ }
+ },
+ }
+ render(h(Comp), root)
+ expect(root.innerHTML).toBe(`<div>baz</div>`)
+ state.value = true
+ await nextTick()
+ expect(root.innerHTML).toBe(`<div><del>baz</del></div>`)
+ })
+
test('textContent unmount prev children', () => {
const fn = vi.fn()
const comp = {