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
parent
commit
ce457f9f4d
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      src/compiler/codegen/index.js
  2. 20
      src/core/instance/render-helpers/render-slot.js
  3. 41
      test/unit/features/component/component-slot.spec.js
  4. 2
      test/unit/modules/compiler/codegen.spec.js

2
src/compiler/codegen/index.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

20
src/core/instance/render-helpers/render-slot.js

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

41
test/unit/features/component/component-slot.spec.js

@ -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>',

2
test/unit/modules/compiler/codegen.spec.js

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

Loading…
Cancel
Save