Browse Source
fix(slot): add a function to return the slot fallback content (#12014)
Co-authored-by: zrh122 <1229550935@qq.com>
dev
Eduardo San Martin Morote
4 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with
55 additions and
10 deletions
-
src/compiler/codegen/index.js
-
src/core/instance/render-helpers/render-slot.js
-
test/unit/features/component/component-slot.spec.js
-
test/unit/modules/compiler/codegen.spec.js
|
|
@ -547,7 +547,7 @@ export function genComment (comment: ASTText): string { |
|
|
|
function genSlot (el: ASTElement, state: CodegenState): string { |
|
|
|
const slotName = el.slotName || '"default"' |
|
|
|
const children = genChildren(el, state) |
|
|
|
let res = `_t(${slotName}${children ? `,${children}` : ''}` |
|
|
|
let res = `_t(${slotName}${children ? `,function(){return ${children}}` : ''}` |
|
|
|
const attrs = el.attrs || el.dynamicAttrs |
|
|
|
? genProps((el.attrs || []).concat(el.dynamicAttrs || []).map(attr => ({ |
|
|
|
// slot props are camelized
|
|
|
|
|
|
@ -7,26 +7,30 @@ import { extend, warn, isObject } from 'core/util/index' |
|
|
|
*/ |
|
|
|
export function renderSlot ( |
|
|
|
name: string, |
|
|
|
fallback: ?Array<VNode>, |
|
|
|
fallbackRender: ?((() => Array<VNode>) | Array<VNode>), |
|
|
|
props: ?Object, |
|
|
|
bindObject: ?Object |
|
|
|
): ?Array<VNode> { |
|
|
|
const scopedSlotFn = this.$scopedSlots[name] |
|
|
|
let nodes |
|
|
|
if (scopedSlotFn) { // scoped slot
|
|
|
|
if (scopedSlotFn) { |
|
|
|
// scoped slot
|
|
|
|
props = props || {} |
|
|
|
if (bindObject) { |
|
|
|
if (process.env.NODE_ENV !== 'production' && !isObject(bindObject)) { |
|
|
|
warn( |
|
|
|
'slot v-bind without argument expects an Object', |
|
|
|
this |
|
|
|
) |
|
|
|
warn('slot v-bind without argument expects an Object', this) |
|
|
|
} |
|
|
|
props = extend(extend({}, bindObject), props) |
|
|
|
} |
|
|
|
nodes = scopedSlotFn(props) || fallback |
|
|
|
nodes = |
|
|
|
scopedSlotFn(props) || |
|
|
|
(fallbackRender && |
|
|
|
(Array.isArray(fallbackRender) ? fallbackRender : fallbackRender())) |
|
|
|
} else { |
|
|
|
nodes = this.$slots[name] || fallback |
|
|
|
nodes = |
|
|
|
this.$slots[name] || |
|
|
|
(fallbackRender && |
|
|
|
(Array.isArray(fallbackRender) ? fallbackRender : fallbackRender())) |
|
|
|
} |
|
|
|
|
|
|
|
const target = props && props.slot |
|
|
|
|
|
@ -109,6 +109,47 @@ describe('Component slot', () => { |
|
|
|
expect(child.$el.children[1].textContent).toBe('slot b') |
|
|
|
}) |
|
|
|
|
|
|
|
it('it should work with previous versions of the templates', () => { |
|
|
|
const Test = { |
|
|
|
render() { |
|
|
|
var _vm = this; |
|
|
|
var _h = _vm.$createElement; |
|
|
|
var _c = _vm._self._c || vm._h; |
|
|
|
return _c('div', [_vm._t("default", [_c('p', [_vm._v("slot default")])])], 2) |
|
|
|
} |
|
|
|
} |
|
|
|
let vm = new Vue({ |
|
|
|
template: `<test/>`, |
|
|
|
components: { Test } |
|
|
|
}).$mount() |
|
|
|
expect(vm.$el.textContent).toBe('slot default') |
|
|
|
vm = new Vue({ |
|
|
|
template: `<test>custom content</test>`, |
|
|
|
components: { Test } |
|
|
|
}).$mount() |
|
|
|
expect(vm.$el.textContent).toBe('custom content') |
|
|
|
}) |
|
|
|
|
|
|
|
it('fallback content should not be evaluated when the parent is providing it', () => { |
|
|
|
const test = jasmine.createSpy('test') |
|
|
|
const vm = new Vue({ |
|
|
|
template: '<test>slot default</test>', |
|
|
|
components: { |
|
|
|
test: { |
|
|
|
template: '<div><slot>{{test()}}</slot></div>', |
|
|
|
methods: { |
|
|
|
test () { |
|
|
|
test() |
|
|
|
return 'test' |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}).$mount() |
|
|
|
expect(vm.$el.textContent).toBe('slot default') |
|
|
|
expect(test).not.toHaveBeenCalled() |
|
|
|
}) |
|
|
|
|
|
|
|
it('selector matching multiple elements', () => { |
|
|
|
mount({ |
|
|
|
childTemplate: '<div><slot name="t"></slot></div>', |
|
|
|
|
|
@ -196,7 +196,7 @@ describe('codegen', () => { |
|
|
|
it('generate slot fallback content', () => { |
|
|
|
assertCodegen( |
|
|
|
'<div><slot><div>hi</div></slot></div>', |
|
|
|
`with(this){return _c('div',[_t("default",[_c('div',[_v("hi")])])],2)}` |
|
|
|
`with(this){return _c('div',[_t("default",function(){return [_c('div',[_v("hi")])]})],2)}` |
|
|
|
) |
|
|
|
}) |
|
|
|
|
|
|
|