Vue3中的监听器。toRefs与toRef的区别

toRefs与toRef

作用:将一个响应式对象的属性 都换转换ref对象

复制代码
<template>
  <h2>姓名:{{ person.name }}</h2>
  <h2>年龄:{{ person.age }}</h2>
  <h2>性别:{{ person.gender }}</h2>
  <button @click="changeName">修改名字</button>
  <button @click="changeAge">修改年龄</button>
  <button @click="changeGender">修改性别</button>
</template>

<script lang="ts" setup name="Person">

import {reactive, toRef, toRefs} from "vue";

let person = reactive({name: '张三', age: 20, gender: '男'})

//通过toRefs 将person中的属性 批量取出(ref),保持响应式
let {name, gender} = toRefs(person)

//通过toRef将person中的一个属性 取出来(ref) 保持响应式
let age = toRef(person, 'age');


const changeName = () => {
  name.value += "*";
}
const changeAge = () => {
  age.value += 1;
}
const changeGender = () => {
  gender.value = "女"
}

</script>

<style scoped>

</style>

computed

作用:根据已有属性计算新的属性,有缓存机制 当已有属性改变时计算属性也会变

复制代码
<template>
  姓:<input type="text" v-model="firstName"/><br/><br/>
  名:<input type="text" v-model="laseName"/><br/><br/>
  <!--  全名:<span>
        {{ fullName }}
        {{ fullName }}
        {{ fullName }}
        {{ fullName }}
        </span>-->
  全名:<input type="text" v-model="fullName"/>
</template>

<script lang="ts" setup name="Person">

import {computed, ref} from "vue";

let firstName = ref("张");
let laseName = ref("三");

//通过计算属性(只读取)不修改
// let fullName = computed(() => {
//   console.log("执行了计算属性 fullName")
//   return firstName.value + "-" + laseName.value;
// })

//通过计算属性(读/写)不修改
let fullName = computed({
  get() {
    //读取
    console.log("fullName get");
    return firstName.value + "-" + laseName.value;
  },
  set(value) {
    //写入
    console.log("fullName set,", value);
    let arr = value.split("-");
    firstName.value = arr[0];
    laseName.value = arr[1];
  }
})


</script>

<style scoped>

</style>

watch 监视

在Vue3中 watch只能监视四中数据

1.ref定义的数据

2.reactive定义的数据

3.函数返回的一个值

4.包含上述内容的数组

监视ref定义的基本数据类型

复制代码
<template>
  <h1>情况一:监视ref定义的数据</h1>
  <h2>count:{{ count }}</h2>
  <button @click="changeCount">点击count+1</button>

</template>

<script lang="ts" setup name="Person">
import {ref, watch} from "vue";

let count = ref(0);

const changeCount = () => {
  count.value += 1;
}

//监视ref定义的数据
const stopWatch = watch(count, (newValue, oldValue) => {
  console.log("count改变了", newValue, oldValue)
  if (count.value >= 5) {
    //停止监视
    stopWatch();
  }
})


</script>

<style scoped>

</style>

监视ref定义的对象类型数据

数据:直接写数据名,监视的是对象的地址,如果要监视对象的属性,启用深度监视

复制代码
<template>
  <h1>情况二:监视ref定义的对象类型数据</h1>
  <h2>姓名:{{ person.name }}</h2>
  <h2>年龄:{{ person.age }}</h2>
  <button @click="changeName">修改姓名</button>
  <button @click="changeAge">修改年龄</button>
  <button @click="changePerson">修改对象</button>
</template>

<script lang="ts" setup name="Person">
import {ref, watch} from "vue";

let person = ref({name: "张三", age: 25});
const changeName = () => {
  person.value.name += "~";
}
const changeAge = () => {
  person.value.age += 1;
}
const changePerson = () => {
  person.value = {name: "李四", age: 30};
}

//监视ref定义的对象类型数据
//监视person对象的整体改变
// watch(person, (newValue, oldValue) => {
//   console.log("person改变了", newValue, oldValue)
// })

//deep: true 深度监视 监视对象下所有的属性
/***
 * 参数1:被监视的数据
 * 参数2:监视的回调函数
 * 参数3,配置对象(deep.immediate.....)
 */
watch(person, (newValue, oldValue) => {
  console.log("person改变了", newValue, oldValue)
}, {deep: true})


</script>

<style scoped>

</style>

监视reactive定义的对象类型数据

默认开启深度监视

复制代码
<template>
  <h1>情况二:监视ref定义的对象类型数据</h1>
  <h2>姓名:{{ person.name }}</h2>
  <h2>年龄:{{ person.age }}</h2>
  <button @click="changeName">修改姓名</button>
  <button @click="changeAge">修改年龄</button>
  <button @click="changePerson">修改对象</button>
  <hr/>
  <h2>测试:{{ obj.a.b.c.d }}</h2>
  <button @click="test">修改d</button>


</template>

<script lang="ts" setup name="Person">
import {reactive, watch} from "vue";

let person = reactive({name: "张三", age: 25});

let obj = reactive({a: {b: {c: {d: 666}}}})


const changeName = () => {
  person.name += "~";
}
const changeAge = () => {
  person.age += 1;
}
const changePerson = () => {
  // person = {name: "李四", age: 30};
  Object.assign(person, {name: "李四", age: 30})
}

const test = () => {
  obj.a.b.c.d = 888;
}

/**
 * 通过 reactive 定义的对象类型数据 监视 默认开启深度监视
 */
watch(person, (newValue, oldValue) => {
  console.log("person改变了", newValue, oldValue)
})

watch(obj, (newValue, oldValue) => {
  console.log("obj改变了", newValue, oldValue)
})
</script>

<style scoped>

</style>

监视ref或者reactive定义的对象类型数据中的 "某个属性"

复制代码
<template>
  <div>
    <h2>监视reactive或者 ref定义的对象类型的某个属性</h2>

    <h2>姓名:{{ person.name }}</h2>
    <h2>年龄:{{ person.age }}</h2>
    <h2>汽车:{{ person.car.c1 }}、{{ person.car.c2 }}</h2>

    <button @click="changeName">修改姓名</button>
    <button @click="changeAge">修改年龄</button>
    <button @click="changeC1">修改第一台车</button>
    <button @click="changeC2">修改第二台车</button>
    <button @click="changeCar">修改整辆车</button>
  </div>
</template>

<script lang="ts" setup name="Person">
import {reactive, watch} from "vue";

let person = reactive({
  name: "张三",
  age: 25,
  car: {
    c1: '比亚迪',
    c2: "雅迪"
  }
})
const changeName = () => {
  person.name += "!";
}
const changeAge = () => {
  person.age += 1;
}
const changeC1 = () => {
  person.car.c1 = "奥迪";
}
const changeC2 = () => {
  person.car.c2 = "小牛";
}
const changeCar = () => {
  person.car = {c1: "爱玛", c2: '小刀'};
}

//监视响应式对象中的某个数据 并且该数据是基本类型,要写函数式
// watch(() => person.name, (newValue, oldValue) => {
//   console.log("name发生了改变",newValue, oldValue);
// })

/**
 * 监视响应式对象中的 某个属性 并且改属性为对象类型,
 * 直接写,写函数,更推荐函数式
 */
watch(() => person.car, (newValue, oldValue) => {
  console.log("car发生了改变", newValue, oldValue);
}, {deep: true})

//直接写的方式监视  只能监视到 属性的改变,并且在替换后 不能在监视
watch(person.car, (newValue, oldValue) => {
  console.log("car发生了改变", newValue, oldValue);
}, {deep: true})

</script>

<style scoped>

</style>

监视上述多个数据

复制代码
<template>
  <div>
    <h2>监视上述多个数据</h2>

    <h2>姓名:{{ person.name }}</h2>
    <h2>年龄:{{ person.age }}</h2>
    <h2>汽车:{{ person.car.c1 }}、{{ person.car.c2 }}</h2>

    <button @click="changeName">修改姓名</button>
    <button @click="changeAge">修改年龄</button>
    <button @click="changeC1">修改第一台车</button>
    <button @click="changeC2">修改第二台车</button>
    <button @click="changeCar">修改整辆车</button>
  </div>
</template>

<script lang="ts" setup name="Person">
import {reactive, watch} from "vue";

let person = reactive({
  name: "张三",
  age: 25,
  car: {
    c1: '比亚迪',
    c2: "雅迪"
  }
})
const changeName = () => {
  person.name += "!";
}
const changeAge = () => {
  person.age += 1;
}
const changeC1 = () => {
  person.car.c1 = "奥迪";
}
const changeC2 = () => {
  person.car.c2 = "小牛";
}
const changeCar = () => {
  person.car = {c1: "爱玛", c2: '小刀'};
}

watch([() => person.name, person.car], (newValue, oldValue) => {
  console.log("person.name, person.car",newValue, oldValue)
}, {deep: true});
</script>

<style scoped>

</style>
相关推荐
狗头大军之江苏分军16 分钟前
iPhone 17 vs iPhone 17 Pro:到底差在哪?买前别被忽悠了
前端
小林coding16 分钟前
再也不怕面试了!程序员 AI 面试练习神器终于上线了
前端·后端·面试
文心快码BaiduComate28 分钟前
WAVE SUMMIT深度学习开发者大会2025举行 文心大模型X1.1发布
前端·后端·程序员
babytiger29 分钟前
python 通过selenium调用chrome浏览器
前端·chrome
passer98135 分钟前
基于webpack的场景解决
前端·webpack
华科云商xiao徐42 分钟前
Java并发编程常见“坑”与填坑指南
javascript·数据库·爬虫
奶昔不会射手1 小时前
css3之grid布局
前端·css·css3
举个栗子dhy1 小时前
解决在父元素上同时使用 onMouseEnter和 onMouseLeave时导致下拉菜单无法正常展开或者提前收起问题
前端·javascript·react.js