Просмотр исходного кода

fix(rumtime-core): custom dom props should be cloned when cloning a hoisted DOM (#3080)

fix #3072
HcySunYang 5 лет назад
Родитель
Сommit
5dbe834858
2 измененных файлов с 26 добавлено и 1 удалено
  1. 12 0
      packages/runtime-dom/__tests__/nodeOps.spec.ts
  2. 14 1
      packages/runtime-dom/src/nodeOps.ts

+ 12 - 0
packages/runtime-dom/__tests__/nodeOps.spec.ts

@@ -0,0 +1,12 @@
+import { nodeOps } from '../src/nodeOps'
+
+describe('nodeOps', () => {
+  test('the _value property should be cloned', () => {
+    const el = nodeOps.createElement('input') as HTMLDivElement & {
+      _value: any
+    }
+    el._value = 1
+    const cloned = nodeOps.cloneNode!(el) as HTMLDivElement & { _value: any }
+    expect(cloned._value).toBe(1)
+  })
+})

+ 14 - 1
packages/runtime-dom/src/nodeOps.ts

@@ -47,7 +47,20 @@ export const nodeOps: Omit<RendererOptions<Node, Element>, 'patchProp'> = {
   },
 
   cloneNode(el) {
-    return el.cloneNode(true)
+    const cloned = el.cloneNode(true)
+    // #3072
+    // - in `patchDOMProp`, we store the actual value in the `el._value` property.
+    // - normally, elements using `:value` bindings will not be hoisted, but if
+    //   the bound value is a constant, e.g. `:value="true"` - they do get
+    //   hoisted.
+    // - in production, hoisted nodes are cloned when subsequent inserts, but
+    //   cloneNode() does not copy the custom property we attached.
+    // - This may need to account for other custom DOM properties we attach to
+    //   elements in addition to `_value` in the future.
+    if (`_value` in el) {
+      ;(cloned as any)._value = (el as any)._value
+    }
+    return cloned
   },
 
   // __UNSAFE__