setup
1、执行时间点
setup在beforeCreate之前完成
beforeCreate:表示组件刚刚被创建出来,组件的data和methods还没有初始化好
created: 表示组件刚刚被创建出来,组件的data和methods已经初始化完成
2、setup注意点
- 由于在执行setup时,还没有执行created生命周期函数,所以在setup中无法使用data和methods
- 由于setup中无法使用data,为了避免错误使用,直接将setup函数中this修改成undefined
- setup函数只能是同步不能是异步的
reactive
1、reactive
reactive是vue3中提供的实现响应式数据的方法
-
在vue2中响应式数据通过defineProperty来实现的
-
而在Vue3中响应式数据是通过ES6的proxy实现
2、reactive注意点:
- reactive参数必须是对象(json/arr)
- 给reactive传递了其他对象
- 如果默认情况下修改对象,界面不会自动更新
- 如果想要更新,需要通过重新赋值的方式
本质:将传入的数据包装成一个Proxy对象
ref
1、什么是ref
- ref和reactive一样,也是用来实现响应式数据的方法
- 由于reactive必须传递一个对象,所以导致在企业开发中如果我们只想让某个变量实现响应式的时候会非常麻烦,所以vue3提供了ref方法,实现对简单值的监听
2、ref本质
- ref底层的本质其实还是reactive
系统会自动根据我们给的ref传入的值将它转换成ref(xx)=> reactive({value: xx})
3、注意点
- 在vue中使用ref传入的值不用通过value获取
- 在js中使用ref的值必须通过value获取
ref 将变量包装成reactive({value: 值}), 设置值的时候就需要使用变量.value形式
在html中则不需要添加:vue会自动给我们添加.vaule
**总结:**设置值时使用变量名.value = 新值,在template中直接使用{{变量名}}即可。
ref与reactive区别
- 在template中
- ref:vue会自动添加
.value - reactive:不会自动添加
- ref:vue会自动添加
vue在解析数据之前,vue是通过__v_isRef来判断,是否是ref类型。
如果有这个私有属性那么就代表是一个ref类型的数据。
可以通过isRef isReactive来判断。
ref、reactive都是递归监听
问题:数据量比较大,非常消耗性能
将复杂json每一层都包装成一个proxy。
非递归监听
1、 shallowReactive
包装第一层。
如果第一层修改,则会更新界面:更新的界面连带着里面有修改的也一同更新
如果第一层不修改,内部修改则不会更新。
2、shallowRef
包装第一层。默认包装value层。
里面内容改变则不会改变
let state2 = shallowRef({
value: {
a: "a",
gf: {
b: "b",
f: {
c: "c",
s: {
d: "d",
},
},
},
}
}); // 直接修改state2.value
state2.value.gf.b = "1";
// triggerRef 触发单个监听
triggerRef(state2);
triggerRef 触发单个监听,而reative类型数据无。
应用场景
一般情况下使用ref和reactive
只有在需要监听的数据量比较大的时候,我们才使用非递归监听shallowReactive/shallowRef
shallowRef
shallowRef本质就是shallowReactive
toRaw
toRaw获取reactive原始数据。
只有通过包装之后的方法才能触发界面更新。
let obj = { name: "ding", age: 24 };
let state3 = reactive(obj);
// obj state3是引用关系
// 直接修改obj, 无法触发界面更新
// 只有通过包装之后的方法才能触界面更新
let func3 = () => {
// obj.name = "deng";
state3.name = 'dere'
console.log(state3);
};
有些操作不需要更新界面或监听:则可以使用toRaw拿到原始数据,对原始数据进行修改。(toRaw不会更新)
let obj = { name: "ding", age: 24 };
let state3 = reactive(obj);
let obj2 = toRaw(state3); // 直接使用obj2
注意:
如果想使用toRaw获取ref的原始数据,则需要加上.value
let obj = { name: "ding", age: 24 };
let state3 = ref(obj);
let obj2 = toRaw(state3.value);
通过toRaw获取ref的state3的原始数据
markRaw
永远都不想被追踪。
使用reactive/ref后,不想被追踪。
let obj3 = { name: "ding", age: 24 };
obj3 = markRaw(obj3);
let state4 = reactive(obj3);
let func4 = () => {
state4.name = "dere";
console.log(state4); // age: 24 name: "dere"
};
值修改但是界面不更新。