fix(hmr): fix custom elements hmr edge cases

This commit is contained in:
Evan You 2021-07-22 18:54:26 -04:00
parent 5b76843b69
commit bff4ea74c5
3 changed files with 26 additions and 12 deletions

View File

@ -290,6 +290,10 @@ export interface ComponentInternalInstance {
* is custom element? * is custom element?
*/ */
isCE?: boolean isCE?: boolean
/**
* custom element specific HMR method
*/
ceReload?: () => void
// the rest are only for stateful components --------------------------------- // the rest are only for stateful components ---------------------------------

View File

@ -7,7 +7,7 @@ import {
ClassComponent, ClassComponent,
isClassComponent isClassComponent
} from './component' } from './component'
import { queueJob, queuePostFlushCb } from './scheduler' import { nextTick, queueJob } from './scheduler'
import { extend } from '@vue/shared' import { extend } from '@vue/shared'
import { warn } from './warning' import { warn } from './warning'
@ -124,7 +124,7 @@ function reload(id: string, newComp: ComponentOptions | ClassComponent) {
// on patch. // on patch.
hmrDirtyComponents.add(component) hmrDirtyComponents.add(component)
// 3. Make sure to unmark the component after the reload. // 3. Make sure to unmark the component after the reload.
queuePostFlushCb(() => { nextTick(() => {
hmrDirtyComponents.delete(component) hmrDirtyComponents.delete(component)
}) })
} }
@ -133,7 +133,10 @@ function reload(id: string, newComp: ComponentOptions | ClassComponent) {
// invalidate options resolution cache // invalidate options resolution cache
instance.appContext.optionsCache.delete(instance.type as any) 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 // 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 // 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. // don't end up forcing the same parent to re-render multiple times.

View File

@ -167,10 +167,9 @@ export class VueElement extends BaseClass {
* @internal * @internal
*/ */
_instance: ComponentInternalInstance | null = null _instance: ComponentInternalInstance | null = null
/**
* @internal private _connected = false
*/ private _styles?: HTMLStyleElement[]
_connected = false
constructor( constructor(
private _def: ComponentOptions & { styles?: string[] }, private _def: ComponentOptions & { styles?: string[] },
@ -262,12 +261,16 @@ export class VueElement extends BaseClass {
instance.isCE = true instance.isCE = true
// HMR // HMR
if (__DEV__) { if (__DEV__) {
instance.appContext.reload = () => { instance.ceReload = () => {
render(this._createVNode(), this.shadowRoot!) this._instance = null
this.shadowRoot!.querySelectorAll('style').forEach(s => { // reset styles
this.shadowRoot!.removeChild(s) if (this._styles) {
}) this._styles.forEach(s => this.shadowRoot!.removeChild(s))
this._styles.length = 0
}
this._applyStyles() this._applyStyles()
// reload
render(this._createVNode(), this.shadowRoot!)
} }
} }
@ -302,6 +305,10 @@ export class VueElement extends BaseClass {
const s = document.createElement('style') const s = document.createElement('style')
s.textContent = css s.textContent = css
this.shadowRoot!.appendChild(s) this.shadowRoot!.appendChild(s)
// record for HMR
if (__DEV__) {
;(this._styles || (this._styles = [])).push(s)
}
}) })
} }
} }