fix(cascader-panel): should not re-init when props's value not change (#2344)

* fix(cascader-panel): should not re-init when props's value not change

fix #2317 #1871

* style: extra space
This commit is contained in:
Simona 2021-06-25 16:08:00 +08:00 committed by GitHub
parent 98714cc3f1
commit 5c4a3cb27b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 2 deletions

View File

@ -686,4 +686,40 @@ describe('CascaderPanel.vue', () => {
await wrapper.setProps({ options: NORMAL_OPTIONS })
expect(vm.getCheckedNodes(true).length).toBe(1)
})
test('should not re-init when props\'s reference change but value not change', async () => {
const mockLazyLoad = jest.fn()
const wrapper = _mount({
template: `
<cascader-panel
v-model="value"
:props="props"
/>
`,
data() {
return {
value: [],
props: {
lazy: true,
lazyLoad: mockLazyLoad,
},
}
},
})
await nextTick()
expect(mockLazyLoad).toBeCalled()
const sameMockLazyLoad = jest.fn()
wrapper.vm.props.lazyLoad = sameMockLazyLoad
await nextTick()
expect(sameMockLazyLoad).not.toBeCalled()
// should re-init when props's value change
const differentMockLazyLoad = jest.fn(lazyLoad)
wrapper.vm.props.lazyLoad = differentMockLazyLoad
await nextTick()
expect(differentMockLazyLoad).toBeCalled()
})
})

View File

@ -36,6 +36,7 @@ import {
coerceTruthyValueToArray,
deduplicate,
isEmpty,
isEqualWithFunction,
} from '@element-plus/utils/util'
import { CommonProps, useCascaderConfig } from './config'
import {
@ -295,7 +296,11 @@ export default defineComponent({
watch(
[ config, () => props.options ],
initStore,
([newConfig, newOptions], [oldConfig, oldOptions]) => {
if (isEqualWithFunction(newConfig, oldConfig) && isEqual(newOptions, oldOptions)) return
initStore()
},
{ deep: true, immediate: true },
)

View File

@ -1,7 +1,9 @@
import type { Ref } from 'vue'
import { getCurrentInstance } from 'vue'
import { camelize, capitalize, extend, hasOwn, hyphenate, isArray, isObject, isString, looseEqual, toRawType } from '@vue/shared'
import { camelize, capitalize, extend, hasOwn, hyphenate, isArray, isObject, isString, isFunction, looseEqual, toRawType } from '@vue/shared'
import isEqualWith from 'lodash/isEqualWith'
import isServer from './isServer'
import type { AnyFunction } from './types'
@ -236,3 +238,18 @@ export function addUnit(value: string | number) {
}
return ''
}
/**
* Enhance `lodash.isEqual` for it always return false even two functions have completely same statements.
* @param obj The value to compare
* @param other The other value to compare
* @returns Returns `true` if the values are equivalent, else `false`.
* @example
* lodash.isEqual(() => 1, () => 1) // false
* isEqualWith(() => 1, () => 1) // true
*/
export function isEqualWithFunction (obj: any, other: any) {
return isEqualWith(obj, other, (objVal, otherVal) => {
return isFunction(objVal) && isFunction(otherVal) ? `${objVal}` === `${otherVal}` : undefined
})
}