- ref—>原有数据的复制,修改数据不会影响原数据但UI界面会更新。
- toRef—>原有数据的引用,修改数据影响原数据但UI界面不更新
- toRefs可以看作toRef的语法糖,toRefs会遍历传入对象的属性。
- reactive的用法与ref的用法相似,也是将数据变成响应式数据,当数据发生变化时UI也会自动更新。不同的是ref用于基本数据类型,而reactive是用于复杂数据类型,比如对象和数组
ref
1.什么是ref
- ref和reactive一样,也是用来实现响应式数据的方法
- 由于reactive必须传递一个对象,所以在实际开发中如果只是想让某个变量实现响应式的时候回非常麻烦
-
2.ref的本质
ref底层其实还是reactive,所以当运行时系统会自动根据传入的ref转换成reactive.
当我们给ref函数传递一个值之后, ref函数底层会自动将ref转换成reactive
ref(18) -> reactive({value: 18})
3.ref注意点
在vue中使用ref的值不用通过value获取
- 在js中使用ref的值必须通过value获取
4.ref获取元素
在vue2中我们可以通过给元素添加ref=‘xxx’,然后在代码中通过refs.xxx的方式来获取元素,在vue3中也可以通过ref来获取元素.
但不是像以下这种熟悉的方式,因为在vue3中没有$和refs这些东西.
<template>
<div>
<div ref="box">我是div</div>
</div>
</template>
<script>
import { ref,onMounted } from "vue";
export default {
setup() {
let box = ref(null); //本质是reactive({value:null})
// 需要在生命周期获取
onMounted(()=>{
// 当界面挂载出来后就会自动执行
console.log(box.value);
})
//接受的是null,原因是setup执行时机比mounted早,dom还没形成
console.log(box.value);
return { box };
},
};
</script>
toRef
什么是toRef
- toRef的本质是引用关系,修改响应式数据会影响原始数据
- toRef当数据发生改变时,界面不会自动更新
- toRef接收两个参数,第一个参数是哪个对象,第二个参数是对象的哪个属性
如果利用toRef将某一个对象中的属性变成了响应式的数据 我们修改响应式的数据是会影响原始数据的 如果数据是通过toRef创建的,修改值后,数据不会触发视图 toRef是引用;它引用的是以前那个对象中的属性 所以你修改后,会影响到原始数据终中的值
所以如果想让响应式数据和以前的数据关联起来,并且想在更新响应式数据的时候不更新UI,那么就使用toRef。
toRef的使用场景
如果想让响应式数据和原始数据关联起来。 并且更新响应式数据后,不想视图更新;那么就可以使用toRef
<template>
<div>
<div>
<div>{{state}}</div>
<button @click="func1">按钮</button>
</div>
</div>
</template>
<script>
import {toRef} from 'vue'
export default {
name: 'App',
setup(){
let obj={name:"张三",age:22}
//将对象中的某一个属性name变成响应式数据
//而不是将对象变成响应式数据
let state=toRef(obj, 'name');
console.log('toRef',state)
function func1(){
state.value="我是李四";
console.log('obj',obj)
console.log('state',state)
}
return {state,func1}
},
}
</script>
toRefs
有的时候,我们希望将对象的多个属性都变成响应式数据,并且要求响应式数据和原始数据关联,并且更新响应式数据的时候不更新界面,就可以使用toRefs,用于批量设置多个数据为响应式数据。(toRef一次仅能设置一个数据)
toRefs接收一个对象作为参数,它会遍历对象身上的所有属性,然后挨个调用toRef执行
<template>
<div>
<h2>toRef的使用</h2>
<p> 姓名:{{name }} </p>
<p>年龄:{{ age }} </p>
<button @click="changeHander">改变内容</button>
</div>
</template>
<script>
import { reactive, toRefs } from "vue"
export default {
name: "App",
setup() {
let state=reactive({
name:'李四',
age:40
})
// toRefs 可以把一个响应式对象转换为普通的对象。
// 该普通对象的每一个值都是ref
// age: ObjectRefImpl {_object: Proxy, _key: "age", __v_isRef: true}
// name: ObjectRefImpl {_object: Proxy, _key: "name", __v_isRef: true}
let state2=toRefs(state);
console.log( 'state2==>ref',state2 )
function changeHander(){
// 由于变成了ref,所以我们需要使用value
state2.name.value="李四222"
state2.age.value=80
}
// ...state虽然我们通过解构的方式。不要在视图上进行点了。但是数据却没有响应
return {...state2,changeHander}
}
};
</script>
总的来说,toRefs就是toRef的一个语法糖,它可以遍历一个对象身上的所有属性,并且挨个调用toRef。
toRefs 可以和 hook 进行搭配使用
<template>
<div>
<h2>toRef的使用</h2>
<p> 姓名:{{name }} </p>
<p>年龄:{{ age }} </p>
<button @click="changeHander">改变内容</button>
<h1>==========奥特曼信息==========</h1>
<p> 姓名:{{name1 }} </p>
<p>年龄:{{ age1 }} </p>
</div>
</template>
<script>
import { reactive, toRefs } from "vue"
export default {
name: "App",
setup() {
let state=reactive({
name:'李四',
age:40
})
// 这里进行了一次解构
let {name,age }=toRefs(state);
// 这样在视图上就直接使用值了
let {name1, age1}=useInfo();
function changeHander(){
name.value="李四222"
age.value=80
}
return {name,age,changeHander, name1, age1}
}
};
// 假设我定义的一个hook
function useInfo(){
let sate=reactive({
name1:"奥特曼",
age1:1000
})
//这里变成响应式并且解构
return { ...toRefs(sate) }
}
</script>
reactive
reactive的用法与ref的用法相似,也是将数据变成响应式数据,当数据发生变化时UI也会自动更新。不同的是ref用于基本数据类型,而reactive是用于复杂数据类型,比如对象和数组
基本数据传递给reactive,reactive并不会将它包装成porxy对象,并且当数据变化时,界面也不会变化需要注意的是,reactive中传递的参数必须是json对象或者数组,如果传递了其他对象(比如new Date()),在默认情况下修改对象,界面不会自动更新,如果也需要具有响应式,可以通过重新赋值的方式实现
<template>
<div>
<p>{{ user }}</p>
<button @click="increase">click me! one year later</button>
</div>
</template>
<script>
import { reactive } from "vue";
export default {
name: "reactive",
setup() {
const user = reactive({ name: "Alice", age: 12 });
function increase() {
++user.age
}
return { user, increase };
},
};
</script>
—————————————————————————————————————————————————
点击跳转线上vue3测试