From 984927a1a98d10ad8af44f2accfb08d34d517610 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 12 Mar 2018 10:50:27 -0400 Subject: [PATCH] fix: fix regression on duplicate component init when using shared data objects fix #7805 --- src/core/vdom/create-component.js | 23 ++++--------- .../modules/vdom/create-component.spec.js | 5 --- .../modules/vdom/patch/edge-cases.spec.js | 32 +++++++++++++++++++ 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/src/core/vdom/create-component.js b/src/core/vdom/create-component.js index 7872bd2a5e5..8957822470b 100644 --- a/src/core/vdom/create-component.js +++ b/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] } } diff --git a/test/unit/modules/vdom/create-component.spec.js b/test/unit/modules/vdom/create-component.spec.js index 6b88ac7d66f..db0c59e3746 100644 --- a/test/unit/modules/vdom/create-component.spec.js +++ b/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 => { diff --git a/test/unit/modules/vdom/patch/edge-cases.spec.js b/test/unit/modules/vdom/patch/edge-cases.spec.js index adcfc95eedc..7555833c289 100644 --- a/test/unit/modules/vdom/patch/edge-cases.spec.js +++ b/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') + }) })