Skip to content

Commit

Permalink
fix: fix regression on duplicate component init when using shared dat…
Browse files Browse the repository at this point in the history
…a objects

fix vuejs#7805
  • Loading branch information
yyx990803 authored and aJean committed Aug 19, 2020
1 parent f47d022 commit 54a22ae
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 22 deletions.
23 changes: 6 additions & 17 deletions src/core/vdom/create-component.js
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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]
}
}
Expand Down
5 changes: 0 additions & 5 deletions test/unit/modules/vdom/create-component.spec.js
Expand Up @@ -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)
Expand All @@ -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 => {
Expand Down
32 changes: 32 additions & 0 deletions test/unit/modules/vdom/patch/edge-cases.spec.js
Expand Up @@ -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')
})
})

0 comments on commit 54a22ae

Please sign in to comment.