From ce457f9f4d48548d5e8763c47d013e23c2b65c12 Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Fri, 16 Apr 2021 17:37:35 +0200 Subject: [PATCH] fix(slot): add a function to return the slot fallback content (#12014) Co-authored-by: zrh122 <1229550935@qq.com> --- src/compiler/codegen/index.js | 2 +- .../instance/render-helpers/render-slot.js | 20 +++++---- .../features/component/component-slot.spec.js | 41 +++++++++++++++++++ test/unit/modules/compiler/codegen.spec.js | 2 +- 4 files changed, 55 insertions(+), 10 deletions(-) diff --git a/src/compiler/codegen/index.js b/src/compiler/codegen/index.js index c4f0195c..acb3ca91 100644 --- a/src/compiler/codegen/index.js +++ b/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 diff --git a/src/core/instance/render-helpers/render-slot.js b/src/core/instance/render-helpers/render-slot.js index 52221f4b..b89f44f7 100644 --- a/src/core/instance/render-helpers/render-slot.js +++ b/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, + fallbackRender: ?((() => Array) | Array), props: ?Object, bindObject: ?Object ): ?Array { 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 diff --git a/test/unit/features/component/component-slot.spec.js b/test/unit/features/component/component-slot.spec.js index 3e5fa883..c6e20e49 100644 --- a/test/unit/features/component/component-slot.spec.js +++ b/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: ``, + components: { Test } + }).$mount() + expect(vm.$el.textContent).toBe('slot default') + vm = new Vue({ + template: `custom content`, + 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: 'slot default', + components: { + test: { + template: '
{{test()}}
', + methods: { + test () { + test() + return 'test' + } + } + } + } + }).$mount() + expect(vm.$el.textContent).toBe('slot default') + expect(test).not.toHaveBeenCalled() + }) + it('selector matching multiple elements', () => { mount({ childTemplate: '
', diff --git a/test/unit/modules/compiler/codegen.spec.js b/test/unit/modules/compiler/codegen.spec.js index d7faa204..a31f751d 100644 --- a/test/unit/modules/compiler/codegen.spec.js +++ b/test/unit/modules/compiler/codegen.spec.js @@ -196,7 +196,7 @@ describe('codegen', () => { it('generate slot fallback content', () => { assertCodegen( '
hi
', - `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)}` ) })