Răsfoiți Sursa

discard vnode children if it has innerHTML or textContent as a prop (fix #3360)

Evan You 10 ani în urmă
părinte
comite
7f429e9c91

+ 6 - 0
src/platforms/web/runtime/modules/dom-props.js

@@ -21,6 +21,12 @@ function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
     }
   }
   for (key in props) {
+    // ignore children if the node has textContent or innerHTML,
+    // as these will throw away existing DOM nodes and cause removal errors
+    // on subsequent patches (#3360)
+    if ((key === 'textContent' || key === 'innerHTML') && vnode.children) {
+      vnode.children.length = 0
+    }
     cur = props[key]
     if (key === 'value') {
       // store value as _value as well since

+ 23 - 0
test/unit/modules/vdom/modules/props.spec.js → test/unit/modules/vdom/modules/dom-props.spec.js

@@ -29,4 +29,27 @@ describe('vdom domProps module', () => {
     const elm = patch(null, vnode)
     expect(elm.value).toBe('0')
   })
+
+  it('should save raw value on element', () => {
+    const value = {}
+    const vnode = new VNode('input', { domProps: { value }})
+    const elm = patch(null, vnode)
+    expect(elm._value).toBe(value)
+  })
+
+  it('should discard vnode children if the node has innerHTML or textContent as a prop', () => {
+    const vnode = new VNode('div', { domProps: { innerHTML: 'hi' }}, [
+      new VNode('span'), new VNode('span')
+    ])
+    const elm = patch(null, vnode)
+    expect(elm.innerHTML).toBe('hi')
+    expect(vnode.children.length).toBe(0)
+
+    const vnode2 = new VNode('div', { domProps: { textContent: 'hi' }}, [
+      new VNode('span'), new VNode('span')
+    ])
+    const elm2 = patch(null, vnode2)
+    expect(elm2.textContent).toBe('hi')
+    expect(vnode2.children.length).toBe(0)
+  })
 })