diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 86c89c59883..a660d849a90 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -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 --------------------------------- diff --git a/packages/runtime-core/src/hmr.ts b/packages/runtime-core/src/hmr.ts index 2021e4f9aa7..45f25ba5137 100644 --- a/packages/runtime-core/src/hmr.ts +++ b/packages/runtime-core/src/hmr.ts @@ -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. diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index fe3f594f69e..b054ccff3e3 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -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) + } }) } }