diff --git a/src/core/vdom/helpers/normalize-scoped-slots.js b/src/core/vdom/helpers/normalize-scoped-slots.js index b2e41bf566a..a9c1bae8bf6 100644 --- a/src/core/vdom/helpers/normalize-scoped-slots.js +++ b/src/core/vdom/helpers/normalize-scoped-slots.js @@ -11,6 +11,7 @@ export function normalizeScopedSlots ( ): any { let res const isStable = slots ? !!slots.$stable : true + const hasNormalSlots = Object.keys(normalSlots).length > 0 const key = slots && slots.$key if (!slots) { res = {} @@ -22,7 +23,8 @@ export function normalizeScopedSlots ( prevSlots && prevSlots !== emptyObject && key === prevSlots.$key && - Object.keys(normalSlots).length === 0 + !hasNormalSlots && + !prevSlots.$hasNormal ) { // fast path 2: stable scoped slots w/ no normal slots to proxy, // only need to normalize once @@ -48,6 +50,7 @@ export function normalizeScopedSlots ( } def(res, '$stable', isStable) def(res, '$key', key) + def(res, '$hasNormal', hasNormalSlots) return res } diff --git a/test/unit/features/component/component-scoped-slot.spec.js b/test/unit/features/component/component-scoped-slot.spec.js index e12932cdd74..ae86dd96ee8 100644 --- a/test/unit/features/component/component-scoped-slot.spec.js +++ b/test/unit/features/component/component-scoped-slot.spec.js @@ -1227,4 +1227,41 @@ describe('Component scoped slot', () => { expect(vm.$el.textContent.trim()).toBe(`2`) }).then(done) }) + + // #9644 + it('should factor presence of normal slots into scoped slots caching', done => { + const Wrapper = { + template: `
+

Default:

+

Content:

+
` + } + + const vm = new Vue({ + data: { ok: false }, + components: { Wrapper }, + template: ` +

ok

+ +
` + }).$mount() + + expect(vm.$el.textContent).not.toMatch(`Default:ok`) + expect(vm.$el.textContent).not.toMatch(`Content:ok`) + vm.ok = true + waitForUpdate(() => { + expect(vm.$el.textContent).toMatch(`Default:ok`) + expect(vm.$el.textContent).toMatch(`Content:ok`) + vm.ok = false + }).then(() => { + expect(vm.$el.textContent).not.toMatch(`Default:ok`) + expect(vm.$el.textContent).not.toMatch(`Content:ok`) + vm.ok = true + }).then(() => { + expect(vm.$el.textContent).toMatch(`Default:ok`) + expect(vm.$el.textContent).toMatch(`Content:ok`) + }).then(done) + }) })