fix(hmr): always force full child component props update in HMR mode
This commit is contained in:
		
							parent
							
								
									5b8883a846
								
							
						
					
					
						commit
						1b946c85df
					
				@ -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(
 | 
			
		||||
@ -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>`)
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user