]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(hmr): fix custom elements hmr edge cases
authorEvan You <yyx990803@gmail.com>
Thu, 22 Jul 2021 22:54:26 +0000 (18:54 -0400)
committerEvan You <yyx990803@gmail.com>
Thu, 22 Jul 2021 22:54:26 +0000 (18:54 -0400)
packages/runtime-core/src/component.ts
packages/runtime-core/src/hmr.ts
packages/runtime-dom/src/apiCustomElement.ts

index 86c89c59883d2639780671e27a26607dc3ec2b40..a660d849a90696fff6c38772801bb3c693d6861b 100644 (file)
@@ -290,6 +290,10 @@ export interface ComponentInternalInstance {
    * is custom element?
    */
   isCE?: boolean
+  /**
+   * custom element specific HMR method
+   */
+  ceReload?: () => void
 
   // the rest are only for stateful components ---------------------------------
 
index 2021e4f9aa79b95cc5f01869ec4e8ae6ed40aefe..45f25ba513773fb9b8cefac772b164507b47db97 100644 (file)
@@ -7,7 +7,7 @@ import {
   ClassComponent,
   isClassComponent
 } from './component'
-import { queueJob, queuePostFlushCb } from './scheduler'
+import { nextTick, queueJob } from './scheduler'
 import { extend } from '@vue/shared'
 import { warn } from './warning'
 
@@ -124,7 +124,7 @@ function reload(id: string, newComp: ComponentOptions | ClassComponent) {
     // on patch.
     hmrDirtyComponents.add(component)
     // 3. Make sure to unmark the component after the reload.
-    queuePostFlushCb(() => {
+    nextTick(() => {
       hmrDirtyComponents.delete(component)
     })
   }
@@ -133,7 +133,10 @@ function reload(id: string, newComp: ComponentOptions | ClassComponent) {
     // invalidate options resolution cache
     instance.appContext.optionsCache.delete(instance.type as any)
 
-    if (instance.parent) {
+    if (instance.ceReload) {
+      // custom element
+      instance.ceReload()
+    } else if (instance.parent) {
       // 4. Force the parent instance to re-render. This will cause all updated
       // components to be unmounted and re-mounted. Queue the update so that we
       // don't end up forcing the same parent to re-render multiple times.
index fe3f594f69e469bbab37e3fd231ae0c7fa89f566..b054ccff3e3cad55cad6c7ce4f588b9794168a6e 100644 (file)
@@ -167,10 +167,9 @@ export class VueElement extends BaseClass {
    * @internal
    */
   _instance: ComponentInternalInstance | null = null
-  /**
-   * @internal
-   */
-  _connected = false
+
+  private _connected = false
+  private _styles?: HTMLStyleElement[]
 
   constructor(
     private _def: ComponentOptions & { styles?: string[] },
@@ -262,12 +261,16 @@ export class VueElement extends BaseClass {
         instance.isCE = true
         // HMR
         if (__DEV__) {
-          instance.appContext.reload = () => {
-            render(this._createVNode(), this.shadowRoot!)
-            this.shadowRoot!.querySelectorAll('style').forEach(s => {
-              this.shadowRoot!.removeChild(s)
-            })
+          instance.ceReload = () => {
+            this._instance = null
+            // reset styles
+            if (this._styles) {
+              this._styles.forEach(s => this.shadowRoot!.removeChild(s))
+              this._styles.length = 0
+            }
             this._applyStyles()
+            // reload
+            render(this._createVNode(), this.shadowRoot!)
           }
         }
 
@@ -302,6 +305,10 @@ export class VueElement extends BaseClass {
         const s = document.createElement('style')
         s.textContent = css
         this.shadowRoot!.appendChild(s)
+        // record for HMR
+        if (__DEV__) {
+          ;(this._styles || (this._styles = [])).push(s)
+        }
       })
     }
   }