Explorar o código

fix: fix regression on duplicate component init when using shared data objects

fix #7805
Evan You %!s(int64=8) %!d(string=hai) anos
pai
achega
984927a1a9

+ 6 - 17
src/core/vdom/create-component.js

@@ -32,7 +32,7 @@ import {
   renderRecyclableComponentTemplate
 } from 'weex/runtime/recycle-list/render-component-template'
 
-// hooks to be invoked on component VNodes during patch
+// inline hooks to be invoked on component VNodes during patch
 const componentVNodeHooks = {
   init (
     vnode: VNodeWithData,
@@ -189,8 +189,8 @@ export function createComponent (
     }
   }
 
-  // merge component management hooks onto the placeholder node
-  mergeHooks(data)
+  // install component management hooks onto the placeholder node
+  installComponentHooks(data)
 
   // return a placeholder vnode
   const name = Ctor.options.name || tag
@@ -234,22 +234,11 @@ export function createComponentInstanceForVnode (
   return new vnode.componentOptions.Ctor(options)
 }
 
-function mergeHooks (data: VNodeData) {
-  if (!data.hook) {
-    data.hook = {}
-  }
+function installComponentHooks (data: VNodeData) {
+  const hooks = data.hook || (data.hook = {})
   for (let i = 0; i < hooksToMerge.length; i++) {
     const key = hooksToMerge[i]
-    const fromParent = data.hook[key]
-    const ours = componentVNodeHooks[key]
-    data.hook[key] = fromParent ? mergeHook(ours, fromParent) : ours
-  }
-}
-
-function mergeHook (one: Function, two: Function): Function {
-  return function (a, b, c, d) {
-    one(a, b, c, d)
-    two(a, b, c, d)
+    hooks[key] = componentVNodeHooks[key]
   }
 }
 

+ 0 - 5
test/unit/modules/vdom/create-component.spec.js

@@ -19,12 +19,10 @@ describe('create-component', () => {
       props: ['msg'],
       render () {}
     }
-    const init = jasmine.createSpy()
     const data = {
       props: { msg: 'hello world' },
       attrs: { id: 1 },
       staticAttrs: { class: 'foo' },
-      hook: { init },
       on: { notify: 'onNotify' }
     }
     const vnode = createComponent(child, data, vm, vm)
@@ -38,9 +36,6 @@ describe('create-component', () => {
     expect(vnode.elm).toBeUndefined()
     expect(vnode.ns).toBeUndefined()
     expect(vnode.context).toEqual(vm)
-
-    vnode.data.hook.init(vnode)
-    expect(init.calls.argsFor(0)[0]).toBe(vnode)
   })
 
   it('create a component when resolved with async loading', done => {

+ 32 - 0
test/unit/modules/vdom/patch/edge-cases.spec.js

@@ -374,4 +374,36 @@ describe('vdom patch: edge cases', () => {
     expect(vm.$el.querySelector('custom-foo').getAttribute('selected')).toBe('1')
     Vue.config.ignoredElements = []
   })
+
+  // #7805
+  it('should not cause duplicate init when components share data object', () => {
+    const Base = {
+      render (h) {
+        return h('div', this.$options.name)
+      }
+    }
+
+    const Foo = {
+      name: 'Foo',
+      extends: Base
+    }
+
+    const Bar = {
+      name: 'Bar',
+      extends: Base
+    }
+
+    const vm = new Vue({
+      render (h) {
+        const data = { staticClass: 'text-red' }
+
+        return h('div', [
+          h(Foo, data),
+          h(Bar, data)
+        ])
+      }
+    }).$mount()
+
+    expect(vm.$el.textContent).toBe('FooBar')
+  })
 })