mirror of https://github.com/vuejs/core.git
Merge 93eafa2d2b
into ba391f5fdf
This commit is contained in:
commit
c030f18c24
|
@ -6,6 +6,7 @@ import {
|
||||||
inject,
|
inject,
|
||||||
nextTick,
|
nextTick,
|
||||||
nodeOps,
|
nodeOps,
|
||||||
|
onMounted,
|
||||||
provide,
|
provide,
|
||||||
ref,
|
ref,
|
||||||
render,
|
render,
|
||||||
|
@ -474,4 +475,55 @@ describe('renderer: component', () => {
|
||||||
`Property '$attrs' was accessed via 'this'. Avoid using 'this' in templates.`,
|
`Property '$attrs' was accessed via 'this'. Avoid using 'this' in templates.`,
|
||||||
).toHaveBeenWarned()
|
).toHaveBeenWarned()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('should not update child component if style is not changed', async () => {
|
||||||
|
const text = ref(0)
|
||||||
|
const spy = vi.fn()
|
||||||
|
|
||||||
|
const ClientOnly = {
|
||||||
|
setup(_: any, { slots }: SetupContext) {
|
||||||
|
const mounted = ref(false)
|
||||||
|
onMounted(() => {
|
||||||
|
mounted.value = true
|
||||||
|
})
|
||||||
|
return () => {
|
||||||
|
if (mounted.value) {
|
||||||
|
return slots.default!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const App = {
|
||||||
|
render() {
|
||||||
|
return h(ClientOnly, null, {
|
||||||
|
default: () => [
|
||||||
|
h('span', null, [text.value]),
|
||||||
|
h(Comp, { style: { width: '100%' } }),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const Comp = {
|
||||||
|
render(this: any) {
|
||||||
|
spy()
|
||||||
|
return null
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = nodeOps.createElement('div')
|
||||||
|
render(h(App), root)
|
||||||
|
expect(serializeInner(root)).toBe(`<!---->`)
|
||||||
|
await nextTick()
|
||||||
|
|
||||||
|
expect(serializeInner(root)).toBe(`<span>0</span><!---->`)
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
text.value++
|
||||||
|
await nextTick()
|
||||||
|
expect(serializeInner(root)).toBe(`<span>1</span><!---->`)
|
||||||
|
// expect Comp to not be re-rendered
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -15,7 +15,14 @@ import {
|
||||||
normalizeVNode,
|
normalizeVNode,
|
||||||
} from './vnode'
|
} from './vnode'
|
||||||
import { ErrorCodes, handleError } from './errorHandling'
|
import { ErrorCodes, handleError } from './errorHandling'
|
||||||
import { PatchFlags, ShapeFlags, isModelListener, isOn } from '@vue/shared'
|
import {
|
||||||
|
PatchFlags,
|
||||||
|
ShapeFlags,
|
||||||
|
isModelListener,
|
||||||
|
isObject,
|
||||||
|
isOn,
|
||||||
|
looseEqual,
|
||||||
|
} from '@vue/shared'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
import { isHmrUpdating } from './hmr'
|
import { isHmrUpdating } from './hmr'
|
||||||
import type { NormalizedProps } from './componentProps'
|
import type { NormalizedProps } from './componentProps'
|
||||||
|
@ -399,7 +406,7 @@ export function shouldUpdateComponent(
|
||||||
for (let i = 0; i < dynamicProps.length; i++) {
|
for (let i = 0; i < dynamicProps.length; i++) {
|
||||||
const key = dynamicProps[i]
|
const key = dynamicProps[i]
|
||||||
if (
|
if (
|
||||||
nextProps![key] !== prevProps![key] &&
|
hasPropValueChanged(nextProps!, prevProps!, key) &&
|
||||||
!isEmitListener(emits, key)
|
!isEmitListener(emits, key)
|
||||||
) {
|
) {
|
||||||
return true
|
return true
|
||||||
|
@ -441,7 +448,7 @@ function hasPropsChanged(
|
||||||
for (let i = 0; i < nextKeys.length; i++) {
|
for (let i = 0; i < nextKeys.length; i++) {
|
||||||
const key = nextKeys[i]
|
const key = nextKeys[i]
|
||||||
if (
|
if (
|
||||||
nextProps[key] !== prevProps[key] &&
|
hasPropValueChanged(nextProps, prevProps, key) &&
|
||||||
!isEmitListener(emitsOptions, key)
|
!isEmitListener(emitsOptions, key)
|
||||||
) {
|
) {
|
||||||
return true
|
return true
|
||||||
|
@ -450,6 +457,19 @@ function hasPropsChanged(
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hasPropValueChanged(
|
||||||
|
nextProps: Data,
|
||||||
|
prevProps: Data,
|
||||||
|
key: string,
|
||||||
|
): boolean {
|
||||||
|
const nextProp = nextProps[key]
|
||||||
|
const prevProp = prevProps[key]
|
||||||
|
if (key === 'style' && isObject(nextProp) && isObject(prevProp)) {
|
||||||
|
return !looseEqual(nextProp, prevProp)
|
||||||
|
}
|
||||||
|
return nextProp !== prevProp
|
||||||
|
}
|
||||||
|
|
||||||
export function updateHOCHostEl(
|
export function updateHOCHostEl(
|
||||||
{ vnode, parent }: ComponentInternalInstance,
|
{ vnode, parent }: ComponentInternalInstance,
|
||||||
el: typeof vnode.el, // HostNode
|
el: typeof vnode.el, // HostNode
|
||||||
|
|
Loading…
Reference in New Issue