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; } }) }
作者:ClyingDeng
链接:https://juejin.cn/post/6935256187034140702
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。