Просмотр исходного кода

fix: avoid exposing internal flags on $scopedSlots

ref #9443
Evan You 7 лет назад
Родитель
Сommit
24b4640c1f

+ 1 - 0
src/core/instance/lifecycle.js

@@ -233,6 +233,7 @@ export function updateChildComponent (
     (parentVnode.data.scopedSlots && !parentVnode.data.scopedSlots.$stable) ||
     (vm.$scopedSlots !== emptyObject && !vm.$scopedSlots.$stable)
   )
+
   // Any static slot children from the parent may have changed during parent's
   // update. Dynamic scoped slots may also have changed. In such cases, a forced
   // update is necessary to ensure correctness.

+ 3 - 2
src/core/vdom/helpers/normalize-scoped-slots.js

@@ -1,6 +1,7 @@
 /* @flow */
 
 import { hasOwn } from 'shared/util'
+import { def } from 'core/util/lang'
 import { normalizeChildren } from 'core/vdom/helpers/normalize-children'
 
 export function normalizeScopedSlots (
@@ -26,8 +27,8 @@ export function normalizeScopedSlots (
       res[key] = proxyNormalSlot(normalSlots, key)
     }
   }
-  res._normalized = true
-  res.$stable = slots ? slots.$stable : true
+  def(res, '_normalized', true)
+  def(res, '$stable', slots ? !!slots.$stable : true)
   return res
 }
 

+ 23 - 0
test/unit/features/component/component-scoped-slot.spec.js

@@ -969,4 +969,27 @@ describe('Component scoped slot', () => {
       }).then(done)
     }
   })
+
+  // regression #9396
+  it('should not force update child with no slot content', done => {
+    const Child = {
+      updated: jasmine.createSpy(),
+      template: `<div></div>`
+    }
+
+    const parent = new Vue({
+      template: `<div>{{ count }}<child/></div>`,
+      data: {
+        count: 0
+      },
+      components: { Child }
+    }).$mount()
+
+    expect(parent.$el.textContent).toBe(`0`)
+    parent.count++
+    waitForUpdate(() => {
+      expect(parent.$el.textContent).toBe(`1`)
+      expect(Child.updated).not.toHaveBeenCalled()
+    }).then(done)
+  })
 })

+ 0 - 23
test/unit/modules/vdom/patch/edge-cases.spec.js

@@ -410,27 +410,4 @@ describe('vdom patch: edge cases', () => {
     expect(vm.$el.textContent).toBe('FooBar')
     expect(inlineHookSpy.calls.count()).toBe(2)
   })
-
-  // regression #9396
-  it('should not force update child with no slot content', done => {
-    const Child = {
-      updated: jasmine.createSpy(),
-      template: `<div></div>`
-    }
-
-    const parent = new Vue({
-      template: `<div>{{ count }}<child/></div>`,
-      data: {
-        count: 0
-      },
-      components: { Child }
-    }).$mount()
-
-    expect(parent.$el.textContent).toBe(`0`)
-    parent.count++
-    waitForUpdate(() => {
-      expect(parent.$el.textContent).toBe(`1`)
-      expect(Child.updated).not.toHaveBeenCalled()
-    }).then(done)
-  })
 })