mirror of
https://gitee.com/vuejs/vue.git
synced 2024-11-30 11:07:51 +08:00
parent
3932a451a1
commit
604e081d04
@ -20,7 +20,7 @@ export function resolveSlots (
|
||||
}
|
||||
// named slots should only be respected if the vnode was rendered in the
|
||||
// same context.
|
||||
if ((child.context === context || child.functionalContext === context) &&
|
||||
if ((child.context === context || child.fnContext === context) &&
|
||||
data && data.slot != null
|
||||
) {
|
||||
const name = child.data.slot
|
||||
|
@ -49,8 +49,8 @@ function FunctionalRenderContext (
|
||||
this._c = (a, b, c, d) => {
|
||||
const vnode: ?VNode = createElement(contextVm, a, b, c, d, needNormalization)
|
||||
if (vnode) {
|
||||
vnode.functionalScopeId = options._scopeId
|
||||
vnode.functionalContext = parent
|
||||
vnode.fnScopeId = options._scopeId
|
||||
vnode.fnContext = parent
|
||||
}
|
||||
return vnode
|
||||
}
|
||||
@ -91,8 +91,8 @@ export function createFunctionalComponent (
|
||||
const vnode = options.render.call(null, renderContext._c, renderContext)
|
||||
|
||||
if (vnode instanceof VNode) {
|
||||
vnode.functionalContext = contextVm
|
||||
vnode.functionalOptions = options
|
||||
vnode.fnContext = contextVm
|
||||
vnode.fnOptions = options
|
||||
if (data.slot) {
|
||||
(vnode.data || (vnode.data = {})).slot = data.slot
|
||||
}
|
||||
|
@ -294,7 +294,7 @@ export function createPatchFunction (backend) {
|
||||
// of going through the normal attribute patching process.
|
||||
function setScope (vnode) {
|
||||
let i
|
||||
if (isDef(i = vnode.functionalScopeId)) {
|
||||
if (isDef(i = vnode.fnScopeId)) {
|
||||
nodeOps.setAttribute(vnode.elm, i, '')
|
||||
} else {
|
||||
let ancestor = vnode
|
||||
@ -308,7 +308,7 @@ export function createPatchFunction (backend) {
|
||||
// for slot content they should also get the scopeId from the host instance.
|
||||
if (isDef(i = activeInstance) &&
|
||||
i !== vnode.context &&
|
||||
i !== vnode.functionalContext &&
|
||||
i !== vnode.fnContext &&
|
||||
isDef(i = i.$options._scopeId)
|
||||
) {
|
||||
nodeOps.setAttribute(vnode.elm, i, '')
|
||||
|
@ -24,9 +24,9 @@ export default class VNode {
|
||||
asyncMeta: Object | void;
|
||||
isAsyncPlaceholder: boolean;
|
||||
ssrContext: Object | void;
|
||||
functionalContext: Component | void; // real context vm for functional nodes
|
||||
functionalOptions: ?ComponentOptions; // for SSR caching
|
||||
functionalScopeId: ?string; // functioanl scope id support
|
||||
fnContext: Component | void; // real context vm for functional nodes
|
||||
fnOptions: ?ComponentOptions; // for SSR caching
|
||||
fnScopeId: ?string; // functioanl scope id support
|
||||
|
||||
constructor (
|
||||
tag?: string,
|
||||
@ -45,9 +45,9 @@ export default class VNode {
|
||||
this.elm = elm
|
||||
this.ns = undefined
|
||||
this.context = context
|
||||
this.functionalContext = undefined
|
||||
this.functionalOptions = undefined
|
||||
this.functionalScopeId = undefined
|
||||
this.fnContext = undefined
|
||||
this.fnOptions = undefined
|
||||
this.fnScopeId = undefined
|
||||
this.key = data && data.key
|
||||
this.componentOptions = componentOptions
|
||||
this.componentInstance = undefined
|
||||
@ -101,6 +101,9 @@ export function cloneVNode (vnode: VNode, deep?: boolean): VNode {
|
||||
cloned.isStatic = vnode.isStatic
|
||||
cloned.key = vnode.key
|
||||
cloned.isComment = vnode.isComment
|
||||
cloned.fnContext = vnode.fnContext
|
||||
cloned.fnOptions = vnode.fnOptions
|
||||
cloned.fnScopeId = vnode.fnScopeId
|
||||
cloned.isCloned = true
|
||||
if (deep) {
|
||||
if (vnode.children) {
|
||||
|
@ -252,8 +252,8 @@ function renderElement (el, isRoot, context) {
|
||||
el.data.attrs[SSR_ATTR] = 'true'
|
||||
}
|
||||
|
||||
if (el.functionalOptions) {
|
||||
registerComponentForCache(el.functionalOptions, write)
|
||||
if (el.fnOptions) {
|
||||
registerComponentForCache(el.fnOptions, write)
|
||||
}
|
||||
|
||||
const startTag = renderStartingTag(el, context)
|
||||
|
@ -779,4 +779,49 @@ describe('Component slot', () => {
|
||||
|
||||
expect(vm.$el.innerHTML).toBe('<div class="foo"><div class="bar">fallback</div></div>')
|
||||
})
|
||||
|
||||
// #7106
|
||||
it('should not lose functional slot across renders', done => {
|
||||
const One = {
|
||||
data: () => ({
|
||||
foo: true
|
||||
}),
|
||||
render (h) {
|
||||
this.foo
|
||||
return h('div', this.$slots.slot)
|
||||
}
|
||||
}
|
||||
|
||||
const Two = {
|
||||
render (h) {
|
||||
return h('span', this.$slots.slot)
|
||||
}
|
||||
}
|
||||
|
||||
const Three = {
|
||||
functional: true,
|
||||
render: (h, { children }) => h('span', children)
|
||||
}
|
||||
|
||||
const vm = new Vue({
|
||||
template: `
|
||||
<div>
|
||||
<one ref="one">
|
||||
<two slot="slot">
|
||||
<three slot="slot">hello</three>
|
||||
</two>
|
||||
</one>
|
||||
</div>
|
||||
`,
|
||||
components: { One, Two, Three }
|
||||
}).$mount()
|
||||
|
||||
expect(vm.$el.textContent).toBe('hello')
|
||||
// trigger re-render of <one>
|
||||
vm.$refs.one.foo = false
|
||||
waitForUpdate(() => {
|
||||
// should still be there
|
||||
expect(vm.$el.textContent).toBe('hello')
|
||||
}).then(done)
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user