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>
相关推荐
正小安19 分钟前
URL.createObjectURL 与 FileReader:Web 文件处理两大法宝的对比
前端·javascript
赵广陆1 小时前
SprinBoot+Vue宠物寄养系统的设计与实现
前端·vue.js·宠物
A黄俊辉A1 小时前
vue3中把封装svg图标为全局组件
前端·javascript·vue.js
老贾爱编程1 小时前
VUE实现刻度尺进度条
前端·javascript·vue.js
F2E_Zhangmo1 小时前
vue如何做到计算属性传参?
前端·javascript·vue.js
繁依Fanyi2 小时前
828华为云征文|华为Flexus云服务器搭建OnlyOffice私有化在线办公套件
服务器·开发语言·前端·python·算法·华为·华为云
叫我小鹏呀2 小时前
vue3中el-table中点击图片放大时,被表格覆盖
前端·javascript·vue.js
我命由我123453 小时前
2.使用 VSCode 过程中的英语积累 - Edit 菜单(每一次重点积累 5 个单词)
前端·javascript·ide·vscode·学习·编辑器·学习方法
四季予你663 小时前
vue2 和 vue3 的区别
前端·javascript·vue.js