-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
readonly(["a", "b", "c"]).includes() tracks dependencies even though array is nonreactive #2493 #6
Comments
问题版本:3.0.2 重现代码import { readonly } from "vue";
import { effect } from "@vue/reactivity";
export default {
setup() {
const readonlyState = readonly(["a", "b", "c"]);
effect(() => {
//readonlyState[0] 不收集deps
readonlyState.includes("a"); //收集deps
});
},
}; 根据issue #2493,@lixiaofa的观点是
问题分析问题在baseHandlers.ts#L85-L88,target在执行getter时如果判断它时Array就会进一步检查 const targetIsArray = isArray(target)
if (targetIsArray && hasOwn(arrayInstrumentations, key)) {
//传入receiver改变了getter调用时的this值为target
return Reflect.get(arrayInstrumentations, key, receiver)
} 在baseHandlers.ts#L40-L71中,对数组执行 const arrayInstrumentations: Record<string, Function> = {}
// instrument identity-sensitive Array methods to account for possible reactive
// values
;(['includes', 'indexOf', 'lastIndexOf'] as const).forEach(key => {
const method = Array.prototype[key] as any
arrayInstrumentations[key] = function(this: unknown[], ...args: unknown[]) {
const arr = toRaw(this)
for (let i = 0, l = this.length; i < l; i++) {
track(arr, TrackOpTypes.GET, i + '') //track会将当前的effect加入对象deps列表中
}
// we run the method using the original args first (which may be reactive)
const res = method.apply(arr, args)
if (res === -1 || res === false) {
// if that didn't work, run it again using raw values.
return method.apply(arr, args.map(toRaw))
} else {
return res
}
}
}) 所以为了解决这个问题,只要在判断条件中加上 const targetIsArray = isArray(target)
if (!isReadonly && targetIsArray && hasOwn(arrayInstrumentations, key)) {
return Reflect.get(arrayInstrumentations, key, receiver)
} |
确保在只读数组中,普通数组方法不会触发依赖收集
1.问题import { readonly } from "vue";
import { effect } from "@vue/reactivity";
export default {
setup() {
const readonlyState = readonly(["a", "b", "c"]);
effect(() => {
//readonlyState[0] 不收集deps
readonlyState.includes("a"); //收集deps
});
},
}; 问题点:
2.问题原因2.1
|
复现代码: import { readonly } from "vue";
import { effect } from "@vue/reactivity";
export default {
name: "App",
setup() {
const arr = readonly(["a", "b", "c", "d"]);
const eff = effect(() => {
void arr[1];
// arr.includes("c");
});
console.log(eff.deps.length);
},
}; 解决的方法: const targetIsArray = isArray(target)
// if (targetIsArray && hasOwn(arrayInstrumentations, key)) {
if (!isReadonly && targetIsArray && hasOwn(arrayInstrumentations, key)) {
return Reflect.get(arrayInstrumentations, key, receiver)
} 遇到的问题: |
readonly(["a", "b", "c"]).includes() tracks dependencies even though array is nonreactive #2493
视频讲解
The text was updated successfully, but these errors were encountered: