Skip to content

Commit

Permalink
fix(hmr): always force full child component props update in HMR mode
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed May 11, 2020
1 parent 5b8883a commit 1b946c8
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 7 deletions.
85 changes: 78 additions & 7 deletions packages/runtime-core/__tests__/hmr.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@ describe('hot module replacement', () => {
expect(serializeInner(root)).toBe(`<div>11</div>`)

// // Update text while preserving state
// rerender(
// parentId,
// compileToFunction(
// `<div @click="count++">{{ count }}!<Child>{{ count }}</Child></div>`
// )
// )
// expect(serializeInner(root)).toBe(`<div>1!1</div>`)
rerender(
parentId,
compileToFunction(
`<div @click="count++">{{ count }}!<Child>{{ count }}</Child></div>`
)
)
expect(serializeInner(root)).toBe(`<div>1!1</div>`)

// Should force child update on slot content change
rerender(
Expand Down Expand Up @@ -147,4 +147,75 @@ describe('hot module replacement', () => {
expect(unmountSpy).toHaveBeenCalledTimes(1)
expect(mountSpy).toHaveBeenCalledTimes(1)
})

// #1156 - static nodes should retain DOM element reference across updates
// when HMR is active
test('static el reference', async () => {
const root = nodeOps.createElement('div')
const id = 'test-static-el'

const template = `<div>
<div>{{ count }}</div>
<button @click="count++">++</button>
</div>`

const Comp: ComponentOptions = {
__hmrId: id,
data() {
return { count: 0 }
},
render: compileToFunction(template)
}
createRecord(id, Comp)

render(h(Comp), root)
expect(serializeInner(root)).toBe(
`<div><div>0</div><button>++</button></div>`
)

// 1. click to trigger update
triggerEvent((root as any).children[0].children[1], 'click')
await nextTick()
expect(serializeInner(root)).toBe(
`<div><div>1</div><button>++</button></div>`
)

// 2. trigger HMR
rerender(
id,
compileToFunction(template.replace(`<button`, `<button class="foo"`))
)
expect(serializeInner(root)).toBe(
`<div><div>1</div><button class="foo">++</button></div>`
)
})

// #1157 - component should force full props update when HMR is active
test('force update child component w/ static props', () => {
const root = nodeOps.createElement('div')
const parentId = 'test2-parent'
const childId = 'test2-child'

const Child: ComponentOptions = {
__hmrId: childId,
props: {
msg: String
},
render: compileToFunction(`<div>{{ msg }}</div>`)
}
createRecord(childId, Child)

const Parent: ComponentOptions = {
__hmrId: parentId,
components: { Child },
render: compileToFunction(`<Child msg="foo" />`)
}
createRecord(parentId, Parent)

render(h(Parent), root)
expect(serializeInner(root)).toBe(`<div>foo</div>`)

rerender(parentId, compileToFunction(`<Child msg="bar" />`))
expect(serializeInner(root)).toBe(`<div>bar</div>`)
})
})
3 changes: 3 additions & 0 deletions packages/runtime-core/src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1270,6 +1270,9 @@ function baseCreateRenderer(
nextVNode: VNode,
optimized: boolean
) => {
if (__DEV__ && instance.type.__hmrId) {
optimized = false
}
nextVNode.component = instance
const prevProps = instance.vnode.props
instance.vnode = nextVNode
Expand Down

0 comments on commit 1b946c8

Please sign in to comment.