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

fix #7805
This commit is contained in:
Evan You 2018-03-12 10:50:27 -04:00
parent cf0b1b745f
commit 984927a1a9
3 changed files with 38 additions and 22 deletions

View File

@ -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]
}
}

View File

@ -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 => {

View File

@ -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')
})
})