reactive的一些补充,先看代码:
-
<template>
-
<div>
-
<p>{{state}}
</p>
-
<button @click="fn">reactive
</button>
-
</div>
-
</template>
-
<script>
-
import { reactive, toRaw }
from
"vue";
-
export
default {
-
setup() {
-
let obj = {
name:
"zs",
age:
18 };
-
let state = reactive(obj);
-
-
function fn() {
-
obj.name =
"ls";
-
console.log(
"obj", obj);
-
console.log(
"state", state);
-
}
-
return { state, fn };
-
},
-
};
-
</script>
-
-
页面打印效果:
我们可以看出改变obj数据吗,state也会跟着改变,但是UI界面却没有刷新,这个是什么问题呢?
我们先看 obj 和 state 的关系
obj和state:引用关系,state的本质是一个Proxy对象,在这个Proxy对象中引用了obj
-
直接修改obj是无法触发UI界面更新的
-
只有通过包装之后的对象来修改,才会触发界面更新
通过改变包装之后的state改变数据:
-
<template>
-
<div>
-
<p>{{state}}
</p>
-
<button @click="fn">reactive
</button>
-
</div>
-
</template>
-
-
<script>
-
import { reactive, toRaw }
from
"vue";
-
export
default {
-
setup() {
-
let obj = {
name:
"zs",
age:
18 };
-
let state = reactive(obj);
-
-
function fn() {
-
// obj.name = "ls";
-
state.name =
"woshinibaba";
-
console.log(
"obj", obj);
-
console.log(
"state", state);
-
}
-
return { state, fn };
-
},
-
};
-
</script>
-
-
效果如下:我们可以看到 obj 和 state 数据都发生了改变,UI界面也更新了
使用toRaw:
-
<template>
-
<div>
-
<p>{{state}}
</p>
-
<button @click="fn">reactive
</button>
-
</div>
-
</template>
-
-
<script>
-
import { reactive, toRaw }
from
"vue";
-
export
default {
-
setup() {
-
let obj = {
name:
"zs",
age:
18 };
-
let state = reactive(obj);
-
-
let obj2 = toRaw(state)
-
-
console.log(
"obj==obj2",obj===obj2)
-
function fn() {
-
// obj.name = "ls";
-
// state.name = "woshinibaba";
-
console.log(
"obj", obj);
-
console.log(
"state", state);
-
console.log(
"obj2", obj2);
-
-
}
-
return { state, fn };
-
},
-
};
-
</script>
-
-
我们可以看出 obj2 和 obj是一样的,也就是说通过toRaw拿到了state的原始数据 obj
我们修改obj2的值:
-
<template>
-
<div>
-
<p>{{state}}
</p>
-
<button @click="fn">reactive
</button>
-
</div>
-
</template>
-
-
<script>
-
import { reactive, toRaw }
from
"vue";
-
export
default {
-
setup() {
-
let obj = {
name:
"zs",
age:
18 };
-
let state = reactive(obj);
-
-
let obj2 = toRaw(state);
-
-
console.log(
"obj==obj2", obj === obj2);
-
function fn() {
-
// obj.name = "ls";
-
// state.name = "woshinibaba";
-
obj2.name =
"woshinidie";
-
console.log(
"obj", obj);
-
console.log(
"state", state);
-
console.log(
"obj2", obj2);
-
}
-
return { state, fn };
-
},
-
};
-
</script>
-
-
效果:我们可以看到通过修改 obj2 会同步修改 obj 和 state ,但是UI界面没有更新
我们可以发现 obj2通过toRaw拿到state的原始数据,进行修改,就不会更新界面。
总结:如果我们想修改 state 的内容而又不想引起UI界面的更新,就只需要用
toRaw
取出它的 “源值” 进行修改就行了。总之,toRaw
是一个用来优化资源加载的方案。
我们看一下 ref 的 toRaw:
我们回顾一下 ref 的本质是什么:
ref本质:reactive ref(obj) —> reactive({value:obj})
ref toRaw代码如下:
-
<template>
-
<div>
-
<p>{{oref}}
</p>
-
<button @click="fn">reactive
</button>
-
</div>
-
</template>
-
<script>
-
import { ref, toRaw }
from
"vue";
-
export
default {
-
setup() {
-
let obj3 = {
name:
"狗子",
age:
88 };
-
let oref = ref(obj3);
-
let toref = toRaw(oref);
-
function fn() {
-
console.log(
"obj3", obj3);
-
console.log(
"oref", oref);
-
console.log(
"toref", toref);
-
}
-
return { oref, fn };
-
},
-
};
-
</script>
-
-
效果:我们可以看出 和 reactive不一样,这是为什么呢?
根据 ref 的本质可以看出 我们应该去拿 .value ,我们再试一下
-
<template>
-
<div>
-
<p>{{oref}}
</p>
-
<button @click="fn">reactive
</button>
-
</div>
-
</template>
-
<script>
-
import { ref, toRaw }
from
"vue";
-
export
default {
-
setup() {
-
let obj3 = {
name:
"狗子",
age:
88 };
-
let oref = ref(obj3);
-
let toref = toRaw(oref.value);
-
console.log(
"obj3 == toref",obj3 == toref)
-
function fn() {
-
console.log(
"obj3", obj3);
-
console.log(
"oref", oref);
-
console.log(
"toref", toref);
-
}
-
return { oref, fn };
-
},
-
};
-
</script>
-
-
我们需要注意的几个点:
- 如果想通过toRaw拿到ref类型的原始数据(创建时传入的那个数据)
- 那么就必须明确告诉toRaw方法,要获取的还是 .value 的值
- 因为经过vue处理之后, .value 中保存的才是当初创建时传入的那个原始数据
下面我们来修改一下 ref 的toRaw :
-
<template>
-
<div>
-
<p>{{oref}}
</p>
-
<button @click="fn">reactive
</button>
-
</div>
-
</template>
-
<script>
-
import { ref, toRaw }
from
"vue";
-
export
default {
-
setup() {
-
let obj3 = {
name:
"狗子",
age:
88 };
-
let oref = ref(obj3);
-
let toref = toRaw(oref.value);
-
console.log(
"obj3 == toref", obj3 == toref);
-
function fn() {
-
console.log(
"obj3", obj3);
-
console.log(
"oref", oref);
-
toref.name =
"我是你爹";
-
console.log(
"toref", toref);
-
}
-
return { oref, fn };
-
},
-
};
-
</script>
-
-
我们可以看出,修改toref 会修改 oref 的数据,obj3没有变化,因为我们拿到的是oref的 .value, 我们可以看到界面没有更新
此时,和 reactive
的 toRaw
效果就完全一致了
总结:
ref/reactive 数据类型特点:
每次修改都会被追踪,都会更新UI界面,但是这样其实是非常消耗性能的
所以如果我们有一些操作不需要被追踪,不需要更新UI界面,那么这个时候,我们就可以通过toRaw方法拿到它的原始数据
对原始数据进行修改,这样就不会被追踪,这样就不会更新UI界面,这样性能就变好了
附录全部代码:
-
<template>
-
<div>
-
<p>{{state}}
</p>
-
<button @click="myfun">changeRaw
</button>
-
<hr>
-
<p>{{oref}}
</p>
-
<button @click="fn">ref
</button>
-
</div>
-
</template>
-
-
<script>
-
import { ref, toRaw, reactive }
from
"vue";
-
export
default {
-
name:
"App",
-
setup() {
-
let obj = {
-
name:
"csl",
-
age:
18,
-
};
-
/*
-
ref/reactive 数据类型特点:
-
每次修改都会被追踪,都会更新UI界面,但是这样其实是非常消耗性能的
-
所以如果我们有一些操作不需要被追踪,不需要更新UI界面,那么这个时候,我们就可以通过toRaw方法拿到它的原始数据
-
对原始数据进行修改,这样就不会被追踪,这样就不会更新UI界面,这样性能就变好了
-
*/
-
let state = reactive(obj);
-
// state 和 obj 关系 引用关系 ,state的本质是一个Proxy对象,在这个Proxy对象中引用了obj
-
let obj2 = toRaw(state);
-
-
// console.log("obj==state", obj === state, obj === obj2); //false true
-
-
function myfun() {
-
// 如果直接修改obj是无法触发界面更新的
-
// 只有通过包装之后的对象来修改,才会触发界面更新
-
// obj.name = "zsssss"
-
console.log(obj)
//{name: "zsssss", age: 18}
-
// state.name = "zsss";
-
// console.log(state);//{name: "zsssss", age: 18}
-
obj2.name =
"zssss";
-
console.log(
"obj2", obj2);
-
console.log(state);
-
}
-
-
let obj3 = {
name:
"狗子",
age:
88 };
-
/*
-
1、ref本质:reactive
-
ref(obj) ——> reactive({value:obj})
-
* */
-
let oref = ref(obj3);
-
// 注意点:如果想通过toRaw拿到ref类型的原始数据(创建时传入的那个数据)
-
// 那么就必须明确告诉toRaw方法,要获取的还是 .value 的值
-
// 因为经过vue处理之后, .value 中保存的才是当初创建时传入的那个原始数据
-
// let toref = toRaw(oref)
-
let toref = toRaw(oref.value)
-
-
function fn(){
-
console.log(
"obj3",obj3)
-
console.log(
"oref",oref)
-
toref.name =
"lllkkkk"
-
console.log(
"toref",toref)
-
-
}
-
-
-
return {
-
state,
-
myfun,
-
oref,
-
fn
-
};
-
},
-
};
-
</script>
markRaw
有的时候,我们希望某些数据是无法被改变的。
markRaw
显式标记一个 对象 (不能是简单类型) 为“永远不会转为响应式代理”,函数返回这个对象本身。
-
const foo = markRaw({})
-
console.log(isReactive(reactive(foo)))
// false
-
-
// 如果被 markRaw 标记了,即使在响应式对象中作属性,也依然不是响应式的
-
const bar = reactive({ foo })
-
console.log(isReactive(bar.foo))
// false
-
<template>
-
<div>
-
<p>{{ state }}
</p>
-
<button @click="fun">click
</button>
-
</div>
-
</template>
-
-
<script>
-
import { reactive, markRaw }
from
"vue";
-
export
default {
-
setup() {
-
let obj = {
name:
"我是你爹",
age:
22 };
-
obj = markRaw(obj)
-
let state = reactive(obj);
-
function fun() {
-
state.name =
"叫爸爸";
-
console.log(state)
-
}
-
return { state, fun };
-
},
-
methods: {},
-
};
-
</script>
-
-
转载:https://blog.csdn.net/csl125/article/details/116235214