vue3中的ref,reacitve,torefs,toref的区别。
从定义数据角度对比: reactive 对比 ref
1. ref 用来定义:基本类型数据;
2. reactive 用来定义:对象(或数组)类型(引用类型);
3. 备注:ref 也可以用来定义对象(或数组)类型数据, 它内部会自动通过 reactive 转为代理对象;
从原理角度对比:
1. ref 通过 Object.defineProperty() 的 get 与 set 来实现响应式(数据劫持);
2. reactive 通过使用 Proxy 来实现响应式(数据劫持), 并通过 Reflect 操作源对象内部的数据;
从使用角度对比:
1. ref 定义的数据:操作数据需要 .value,读取数据时模板中直接读取不需要 .value;
2. reactive 定义的数据:操作数据与读取数据:均不需要 .value;
const obj = ref({ name:'张三' }) const count = ref(1) const obj = reactive({ count })
toRef 接受两个参数:第一个参数为源对象,第二个参数为源对象中的属性名;
获取数据值的时候需要加 .value;
使用场景:有一个响应式对象数据,但是模版中只需要使用其中一项数据;
使用 toRef 转化后生成的 ref 数据,如果是引用类型数据时,那么它不是原始数据的拷贝,而是原始数据的引用,改变它的数据也会同时改变原始数据;
const obj = reactive({
name:'张三',
city:'西安',
});
// let {city} = obj; // 注意:从响应式数据对象中解构出的属性数据,不再是响应式数据
let city = toRef(obj,'city');
ref 创建一个响应式对象,如果传入参数是对象,那么与对象所有嵌套属性都维持数据响应。它的作用是 data 选项 般的存在,即组件内部状态。ref 值改变会触发页面渲染,同时能作为 props 或 事件参数 进行组件通信;
toRef 是对传入对象指定属性的响应式绑定,值改变不会更新视图。因此用它创建的变量不作用于模版渲染,而是用来接收诸如 props 的引用式传递;
toRefs 用于将响应式对象转换为普通对象,其中普通对象的每个属性都是指向原始对象相应属性的 ref,两者保持引用关系;
toRefs 常用于 ES6 的解构赋值操作。但是,对一个响应式对象直接解构时,解构后的数据将不再有响应式,而使用 toRefs 可以方便解决这个问题;
获取数据值的时候需要加 .value;
使用 toRefs 转化后生成的 ref 数据如果是引用类型数据时,那么它不是原始数据的拷贝,而是原始数据的引用,改变它的数据也会同时改变原始数据;
其作用和 toRef 类似,只不过 toRef 是对一个个属性手动赋值,而 toRefs 是自动解构赋值;
使用场景:剥离响应式对象(解构|展开),想使用响应式对象中的多个或者所有属性做为响应式数据;
总结
ref、reactive是在 setup() 声明组件内部状态用的, 这些变量通常都要 return 出去,除了供 < template > 或渲染函数渲染视图,也可以作为 props 或 emit 参数 在组件间传递。它们的值变更可触发页面渲染;
toRef、toRefs 用于处理 组件/函数 传递的响应式数据,如:在接收父组件 props 时 / 或 composables 组合式函数返回数据时建立起某些属性的响应式引用;
通过 ref 包装的属性在 setup 函数内都需要通过 .value 去访问它值 ( template 模版内不用 )。因此,ref、toRef 创建的变量值都需要用变量 .value 读取。reactive 则不用,因为会自动解包分配给它的 ref。
至于 toRefs,如果是解构赋值,如: const { state1, state2 } = toRefs(props),值需要这样获取:state1.value.count;
若整体赋给一个变量,如:const state = toRefs(props),则是 state.state1.value。
只有 toRefs 可以解构;
以上四种方式声明的变量在通过 props 或 事件 传递时,均会维持其响应性;