1.ref和reactive
区别:
1.ref创建的变量必须使用.value (可以使用 volar 插件自动添加. value )。
2. reactive 重新分配一个新对象,会失去响应式(可以使用 Object . assign 去整体替换)。let game=reactive([ {id:'1',name:'game1'}, {id:'2',name:'game2'}, {id:'3',name:'game3'} ]) function changeGame(){ Object.assign(game,reactive([ {id:'1',name:'game5'}, {id:'2',name:'game6'}, {id:'3',name:'game7'} ])) }
使用原则:
1. 若需要一个基本类型的响应式数据必须使用 ref 。
2.若需要一个响应式对象,层级不深, ref 、 reactive 都可以。3.若需要一个响应式对象,且层级较深,推荐使用 reactive 。
2.toRef和toRefs
- toRef: 复制 reactive 里的单个属性并转成 ref
- toRefs: 复制 reactive 里的所有属性并转成 ref
let info = reactive({
name: 'Tony',
greet: 'Hello'
})
// 复制 info 里的 greet 属性
let rGreet = toRef(info, 'greet')
rGreet.value = 'world!'
rGreet 改变 则 info里面的greet改变
let info = reactive({
name: 'Tony',
greet: 'Hello'
})
// 复制整个 info
let rInfo = toRefs(info)
// 更改 rInfo.greet
const onChangeGreet = () => {
rInfo.greet.value = 'world!'
}
3.computed 计算属性
<template>
<div>
计算属性
<div><span>姓:</span> <input type="text" v-model="xing"></div>
<div><span>名:</span> <input type="text" v-model="ming"></div>
<div><span>全名:{{ funllname }}</span> </div>
<div><span>全名:{{ funllname }}</span> </div>
<div><span>全名:{{ funllname }}</span> </div>
<button @click="changename">改变姓名为li-si</button>
</div>
</template>
<script lang="ts" setup>
import { ref,computed } from 'vue';
let xing=ref("zhang")
let ming=ref("san")
// computed有缓存 多次调用没有改变的话只执行一次
// 这么定义的funllname是只读的
// let funllname=computed(()=>{
// return xing.value+"-"+ming.value
// })
// 这么定义才是funllname可读写的
let funllname=computed({ //funllname是个ref定义的响应式数据
get() {
return xing.value+"-"+ming.value
},
set(name){
console.log(name)
let [str1,str2]=name.split("-")
xing.value=str1
ming.value=str2
}
})
function changename(){
//funllname是个ref定义的响应式数据
funllname.value="li-si"
}
</script>
4.watch监听
情况一:监视ref定义的基本类型
<template> <div> 情况一:监视ref定义的基本类型 sumde:{{ sum }} <button @click="addsum">sum1+1</button> </div> </template> <script lang="ts"> export default { name:'watch' } </script> <script lang="ts" setup > import { ref,watch } from "vue"; let sum=ref(1) function addsum(){ sum.value =sum.value+1 } // 情况一:监视ref定义的基本类型 let stopWatch=watch(sum,(newvalue,oldvalue)=>{ console.log(newvalue,oldvalue) if(newvalue>=10){ stopWatch() } }) </script>
情况二.监听ref定义的对象类型数据
·若修改的是 ref 定义的对象中的属性, newValue 和 oldValue 都是新值,因为它们是同一个对象。(person.value.name+="~")
.若修改整个 ref 定义的对象, newValue 是新值, oldValue 是旧值,因为不是同一个对象了。( person.value={name:'张三222',age:118} //地址值发生了变化)<template> <div> 情况二:监视ref定义的对象类型 <p> 姓名:{{ person.name}}</p> <p> 年龄:{{person.age}}</p> <button @click="changename">改变姓名</button> <button @click="changeage">改变年龄</button> <button @click="changeperson">改变person</button> </div> </div> </template> <script lang="ts" setup > // 情况二:监视ref定义的对象类型 let person=ref({name:'张三',age:18}) function changename(){ person.value.name+="~" } function changeage(){ person.value.age+=1 } function changeperson(){ // person.value.name+="~" // person.value.age+=1 person.value={name:'张三222',age:118} //地址值发生了变化 } watch(person,(newvalue,oldvalue)=>{ // 此时监视的是地址值的变化(changeage(),changename()person无变化), // 若想监视对象内部属性的变化,要开启深度监视 console.log("person改变了",newvalue,oldvalue) }) watch(person,(newvalue,oldvalue)=>{ // 此时监视的是地址值的变化(changeage(),changename()方法,person无变化), // 若想监视对象内部属性的变化,要开启深度监视 console.log("person改变了",newvalue,oldvalue) },{deep:true}) </script>
情况三:监视reactive定义的对象数据类型 地址值没有发生变化,所以newvalue和oldvalue值一样
<div> 情况三:监视reactive定义的对象类型 <p> 姓名:{{ person.name}}</p> <p> 年龄:{{person.age}}</p> <button @click="changename">改变姓名</button> <button @click="changeage">改变年龄</button> <button @click="changeperson">改变person</button> </div> // 情况三:监视reactive定义的对象类型 let person3=reactive({name:'张三',age:18}) function changename3(){ person3.name+="~" } function changeage3(){ person3.age+=1 } function changeperson3(){ Object.assign(person3,{name:'张三222',age:118})//把相同的属性值赋值给person3 } watch(person3,(newvalue,oldvalue)=>{ //三个方法person3都发生了改变 // 监视reactive定义的对象类型:默认开启深度监视,隐式的创建,且关不掉 console.log("person改变了",newvalue,oldvalue) })
*情况四
监视 ref 或 reactive 定义的【对象类型】数据中的某个属性,注意点如下:
1.若该属性值不是【对象类型】,需要写成函数形式。
2.若该属性值是依然是【对象类型】,可直接编,也可写成函数,不过建议写成函数。结论:监视的要是对象里的属性,最好写函数式,若监视的是地址性的改变,最好手动都开启{deep:true}(ref或者reactive)
let person4=reactive({ name:"zhangsan", age:18, car:{ brand:"奥迪", peice:100 } }) watch(()=>{return person4.age},(newvalue,oldvalue)=>{ console.log("person改变了",newvalue,oldvalue) }) watch(()=>{return person4.car},(newvalue,oldvalue)=>{ console.log("person改变了",newvalue,oldvalue) },{deep:true})