toRef
ref本质是复制 不会影响原始数据
toRef本质是引用 会影响原始数据但不更新界面
// 利用ref将某一对象中的属性变成响应式数据,修改响应式数据是不会影响到原始数据的
// let state5 = ref(obj.name);
// 使用toRef 会影响响应式数据但不会更新界面
let state5 = toRef(obj, 'name');
toRefs
一个变量需要多个属性变为响应式数据
let obj = { name: "aaa", age: 24 };
let state5 = toRefs(obj);
let func5 = () => {
// state5.value = 'dd';
state5.age.value = 33;
console.log(state5);
};
更新数据不更新界面
toraw、toRefs、shallowRef、shallowReactive都是用来做性能优化的
customRef
自定义ref:返回一个ref对象,可以显示地控制依赖追踪和触发响应
let state = myRef("../public/data.json");
let func = () => {
state.value += 1;
};
// setup外
function myRef(value) {
return customRef((track, trigger) => {
fetch(value)
.then((res) => {
return res.json();
})
.then((data) => {
value = data;
trigger();
console.log(data);
})
.catch((err) => {
console.log(err);
});
return {
get() {
track(); // 需要追踪变化的
// 不能读取数据
return value;
},
set(newValue) {
value = newValue;
trigger(); // 触发界面更新
console.log("set");
},
};
});
}
ref获取元素
<div ref="box">box</div>
let box = ref(null);
onMounted(() => {
console.log("onMounted", box.value); // onMounted <div>box</div>
});
console.log(box.value); //null 先执行
return {box}
setup在beforeCreate之前执行
readonly
readonly全部只读;shallowReadonly只有第一层不可修改;但修改值后不触发界面更新
两者isReadonly均为true
let state1 = readonly({ id: 1, name: "ddd" });
let state2 = shallowReadonly({ id: 1, son: { name: "yyy" } });
let func = () => {
state2.id = 2;
state2.son.name = "2222";
// shallowReadonly 只有第一层不可修改;但修改值后不触发界面更新
console.log(state2); // id: 1 son: {name: "2222"}
console.log(isReadonly(state1), isReadonly(state2)); // true true
readonly与const区别
const: 不能给变量重新赋值,赋值保护
readonly:不能给属性重新赋值,属性保护
const state3 = { id: 1, name: "ddd" };
state3.id = 3; // 属性赋值
state3.name = '3333';
state3.of = 'ff';
// state3 = 3; 直接赋值就不行
console.log(state3); // {id: 3, name: "3333", of: "ff"}
vue3响应数据本质
vue2:通过defineProperty来实现响应式数据
vue3:通过Proxy来实现响应式数据
// vue3响应数据本质
let obj = { name: 'dy', age: 18 };
let state = new Proxy(obj, {
get(obj, key) {
console.log(obj, key); // { name: 'dy', age: 18 } name
return Reflect.get(obj, key);
},
set(obj, key, value) {
obj[key] = value;
console.log(obj, key, value);
return true; // 变量为数组时,需要返回true,表示上一次操作成功
}
});
state.name = 'dddd';
console.log(state.name);
shallowReative、shallowRef本质
function shallowRef(val) {
return shallowReactive({ value: val });
}
function shallowReactive(obj) {
return new Proxy(obj, {
get(obj, key) {
console.log(obj, key);
return obj[key];
},
set(obj, key, value) {
obj[key] = value;
console.log('数据修改了,更新页面');
return true;
}
})
}
shallowReactive、shallowRef修改,数据均会修改。区别在于修改第一层会触发页面更新,连带着内层数据修改变化。第一层不修改则只会触发数据更新
reactive、ref本质
function ref(val) {
return reactive({ value: val });
}
function reactive(obj) {
if (typeof obj === 'object') {
if (obj instanceof Array) {
// 如果是一个数组,那么取出数组中的每一个元素
// 再判断每个元素是否又是一个对象,如果是再包装成Proxy
obj.forEach((item, index) => {
if (typeof item === 'object') {
obj[index] = reactive(item);
}
})
} else {
// 对象,里面如果还是对象就再包装
for (let key in obj) {
let item = obj[key];
if (typeof item === 'object') {
obj[key] = reactive(item);
}
}
}
}
return new Proxy(obj, {
get(obj, key) {
console.log(obj[key]);
return obj[key];
},
set(obj, key, value) {
obj[key] = value;
console.log('set');
return true;
}
})
}
readonly、shallowReadonly本质
function shallowReadonly(obj) {
return new Proxy(obj, {
get(obj, key) {
return obj[key];
},
set(obj, key, val) {
// obj[key] = val;
console.warn('只读,不能修改');
}
})
}
function readonly(obj) {
if (typeof obj === 'object') {
if (obj instanceof Array) {
obj.forEach((item, index) => {
if (typeof item === 'obj') {
obj[index] = readonly(item);
}
})
} else {
for (let key in obj) {
let item = obj[key];
if (typeof item === 'object') {
obj[key] = readonly(item);
}
}
}
}
return new Proxy(obj, {
get(obj, key) {
return Reflect.get(obj, key);
},
set(obj, key, value) {
// obj[key] = value;
console.warn('只读,不能修改');
return true;
}
})
}