Jelajahi Sumber

fix replaced component root nodes losing parent scopeId (fix #4774)

Evan You 9 tahun lalu
induk
melakukan
90a455c95c
2 mengubah file dengan 35 tambahan dan 2 penghapusan
  1. 7 2
      src/core/vdom/patch.js
  2. 28 0
      test/unit/features/options/_scopeId.spec.js

+ 7 - 2
src/core/vdom/patch.js

@@ -260,9 +260,14 @@ export function createPatchFunction (backend) {
   // of going through the normal attribute patching process.
   function setScope (vnode) {
     let i
-    if (isDef(i = vnode.context) && isDef(i = i.$options._scopeId)) {
-      nodeOps.setAttribute(vnode.elm, i, '')
+    let ancestor = vnode
+    while (ancestor) {
+      if (isDef(i = ancestor.context) && isDef(i = i.$options._scopeId)) {
+        nodeOps.setAttribute(vnode.elm, i, '')
+      }
+      ancestor = ancestor.parent
     }
+    // for slot content they should also get the scopeId from the host instance.
     if (isDef(i = activeInstance) &&
         i !== vnode.context &&
         isDef(i = i.$options._scopeId)) {

+ 28 - 0
test/unit/features/options/_scopeId.spec.js

@@ -40,4 +40,32 @@ describe('Options _scopeId', () => {
     expect(vm.$el.children[0].children[0].hasAttribute('foo')).toBe(true)
     expect(vm.$el.children[0].children[0].hasAttribute('bar')).toBe(true)
   })
+
+  // #4774
+  it('should not discard parent scopeId when component root element is replaced', done => {
+    const vm = new Vue({
+      _scopeId: 'data-1',
+      template: `<div><child ref="child" /></div>`,
+      components: {
+        child: {
+          _scopeId: 'data-2',
+          data: () => ({ show: true }),
+          template: '<div v-if="show"></div>'
+        }
+      }
+    }).$mount()
+
+    const child = vm.$refs.child
+
+    expect(child.$el.hasAttribute('data-1')).toBe(true)
+    expect(child.$el.hasAttribute('data-2')).toBe(true)
+
+    child.show = false
+    waitForUpdate(() => {
+      child.show = true
+    }).then(() => {
+      expect(child.$el.hasAttribute('data-1')).toBe(true)
+      expect(child.$el.hasAttribute('data-2')).toBe(true)
+    }).then(done)
+  })
 })