Parcourir la source

fix(custom-element): preserve appContext during update (#12455)

close #12453
edison il y a 11 mois
Parent
commit
013749e75e

+ 35 - 0
packages/runtime-dom/__tests__/customElement.spec.ts

@@ -1425,6 +1425,41 @@ describe('defineCustomElement', () => {
 
       expect(e.shadowRoot?.innerHTML).toBe('<div>app-injected</div>')
     })
+
+    test('with hmr reload', async () => {
+      const __hmrId = '__hmrWithApp'
+      const def = defineComponent({
+        __hmrId,
+        setup() {
+          const msg = inject('msg')
+          return { msg }
+        },
+        render(this: any) {
+          return h('div', [h('span', this.msg), h('span', this.$foo)])
+        },
+      })
+      const E = defineCustomElement(def, {
+        configureApp(app) {
+          app.provide('msg', 'app-injected')
+          app.config.globalProperties.$foo = 'foo'
+        },
+      })
+      customElements.define('my-element-with-app-hmr', E)
+
+      container.innerHTML = `<my-element-with-app-hmr></my-element-with-app-hmr>`
+      const el = container.childNodes[0] as VueElement
+      expect(el.shadowRoot?.innerHTML).toBe(
+        `<div><span>app-injected</span><span>foo</span></div>`,
+      )
+
+      // hmr
+      __VUE_HMR_RUNTIME__.reload(__hmrId, def as any)
+
+      await nextTick()
+      expect(el.shadowRoot?.innerHTML).toBe(
+        `<div><span>app-injected</span><span>foo</span></div>`,
+      )
+    })
   })
 
   // #9885

+ 3 - 1
packages/runtime-dom/src/apiCustomElement.ts

@@ -533,7 +533,9 @@ export class VueElement
   }
 
   private _update() {
-    render(this._createVNode(), this._root)
+    const vnode = this._createVNode()
+    if (this._app) vnode.appContext = this._app._context
+    render(vnode, this._root)
   }
 
   private _createVNode(): VNode<any, any> {