简记Vue3(二)—— computed、watch、watchEffect

个人简介

👀个人主页: 前端杂货铺

🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展

📃个人状态: 研发工程师,现效力于中国工业软件事业

🚀人生格言: 积跬步至千里,积小流成江海

🥇推荐学习:🍍前端面试宝典 🎨100个小功能 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js实战 🍒Three.js

🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧

文章目录

    • 前言
    • computed
    • watch
      • [监听 ref 定义的基本类型数据。](#监听 ref 定义的基本类型数据。)
      • [监听 ref 定义的对象类型数据](#监听 ref 定义的对象类型数据)
      • [监听 reactive 定义的对象类型数据](#监听 reactive 定义的对象类型数据)
      • [监听 ref 或 reactive 定义的对象类型数据的某个属性](#监听 ref 或 reactive 定义的对象类型数据的某个属性)
      • 监视多个属性
      • watchEffect

前言

重拾 Vue3,查缺补漏、巩固基础。

computed

计算属性只读、可修改(getter setter)。

javascript 复制代码
<template>
  <div class="person">
    <input type="text" v-model="firstName" /><br />
    <input type="text" v-model="lastName" /><br />
    {{ fullName }} <br />
    <button @click="changeName">changeName(computed)</button>
  </div>
</template>

<script lang="ts" setup>
import { ref, computed } from "vue";
const firstName = ref("zhang");
const lastName = ref("san");

// 只读计算属性
// const fullName = computed(() => {
//   return (
//     firstName.value.slice(0, 1).toUpperCase() +
//     firstName.value.slice(1) +
//     "-" +
//     lastName.value
//   );
// });

// getter setter
const fullName = computed({
  get() {
    return (
      firstName.value.slice(0, 1).toUpperCase() +
      firstName.value.slice(1) +
      "-" +
      lastName.value
    );
  },
  set(val) {
    const [str1, str2] = val.split("-");
    firstName.value = str1;
    lastName.value = str2;
  },
});

function changeName() {
  fullName.value = "li-si";
}
</script>

<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
button {
  margin: 0 5px;
}
</style>

watch

Vue3 中的 watch 只能监视以下四种数据:

  • ref 定义的数据
  • reactive 定义的数据
  • 函数返回一个值(getter函数)
  • 一个包含上述内容的数组

监听 ref 定义的基本类型数据。

javascript 复制代码
<template>
  <div class="person">
    {{ sum }} <br />
    <button @click="changeSum">changeSum</button>
  </div>
</template>

<script lang="ts" setup>
import { ref, watch } from "vue";
const sum = ref(0);

function changeSum() {
  sum.value += 1;
}

// sum 值大于 5 时停止监视
const stopWatch = watch(sum, (newValue, oldVallue) => {
  console.log(newValue, oldVallue);
  if (newValue > 5) {
    stopWatch();
  }
});
</script>

<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
button {
  margin: 0 5px;
}
</style>

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

修改的是 ref 定义的对象中的属性,newValue 和 oldValue 都是新值,因为它们是同一个对象。

修改整个 ref 定义的对象,newValue 是新值,oldValue 是旧值,因为不是同一个对象。

javascript 复制代码
<template>
  <div class="person">
    {{ person.name }} <br />
    {{ person.age }} <br />
    <button @click="changeName">changName</button>
    <button @click="changePerson">changePerson</button>
  </div>
</template>

<script lang="ts" setup>
import { ref, watch } from "vue";
const person = ref({
  name: "zhangsan",
  age: 10,
});

function changeName() {
  person.value.name = "lisi";
}

function changePerson() {
  person.value = { name: "wangwu", age: 20 };
}

// 深度监听 person
watch(person, (newValue, oldValue) => {
    console.log(newValue, oldValue);
  },{ deep: true ));
</script>

<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
button {
  margin: 0 5px;
}
</style>

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

监视 reactive 定义的对象类型数据时,默认开启深度监视,且无法取消。

java 复制代码
<template>
  <div class="person">
    {{ person.name }} <br />
    {{ person.age }} <br />
    <button @click="changeName">changName</button>
    <button @click="changePerson">changePerson</button>
  </div>
</template>

<script lang="ts" setup>
import { reactive, watch } from "vue";
const person = reactive({
  name: "zhangsan",
  age: 10,
});

function changeName() {
  person.name = "lisi";
}

function changePerson() {
  Object.assign(person, { name: "wangwu", age: 20 });
}

watch(person, (newValue, oldValue) => {
  console.log(newValue, oldValue);
});
</script>

<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
button {
  margin: 0 5px;
}
</style>

监听 ref 或 reactive 定义的对象类型数据的某个属性

  • 若该属性值不是对象类型。需要写成函数形式
  • 若该属性值是对象类型。可以直接 . 出来,也可以写成函数(推荐)

监视的要是对象里的属性,最好写成函数式。

注意点:若监视的是地址值,需要关注对象内部,需要手动开启深度监听。

java 复制代码
<template>
  <div class="person">
    {{ person.name }} : {{ person.age }}
    {{ person.car.c1 }}
    {{ person.car.c2 }}
    <button @click="changeName">changeName</button>
    <button @click="changeC1">changeC1</button>
    <button @click="changeC2">changeC2</button>
    <button @click="changeCar">changeCar</button>
  </div>
</template>

<script lang="ts" setup>
  import { reactive, watch } from 'vue'
  const person = reactive({
    name: '张三',
    age: 20,
    car: {
      c1: '大众',
      c2: '小米'
    }
  })

  function changeName() {
    person.name = '李四';
  }

  function changeC1() {
    person.car.c1 = '奥迪';
  }

  function changeC2() {
    person.car.c2 = '宝马';
  }

  function changeCar() {
    person.car = {c1: "雅迪", c2: "爱玛"};
  }

  watch(() => person.name, (newValue, oldValue) => {
    console.log('name changed', newValue, oldValue);
  })

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

<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
button {
  margin: 0 5px;
}
</style>




监视多个属性

使用数组包裹的形式,实现同时监听多个属性。

java 复制代码
<template>
  <div class="person">
    {{ person.name }} : {{ person.age }}
    {{ person.car.c1 }}
    {{ person.car.c2 }}
    <button @click="changeName">changeName</button>
    <button @click="changeC1">changeC1</button>
    <button @click="changeC2">changeC2</button>
    <button @click="changeCar">changeCar</button>
  </div>
</template>

<script lang="ts" setup>
  import { reactive, watch } from 'vue'
  const person = reactive({
    name: '张三',
    age: 20,
    car: {
      c1: '大众',
      c2: '小米'
    }
  })

  function changeName() {
    person.name = '李四';
  }

  function changeC1() {
    person.car.c1 = '奥迪';
  }

  function changeC2() {
    person.car.c2 = '宝马';
  }

  function changeCar() {
    person.car = {c1: "雅迪", c2: "爱玛"};
  }

  watch([() => person.name, () => person.car.c1], (newValue, oldValue) => {
    console.log('name or car changed', newValue, oldValue);
  })
</script>

<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
button {
  margin: 0 5px;
}
</style>

watchEffect

watchEffect 会立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行。

java 复制代码
<template>
  <div class="person">
    <h2>当前求和为:{{ sum }}</h2>
    <button @click="changeNum">changeNum</button>
  </div>
</template>

<script lang="ts" setup>
  import { ref, watchEffect } from 'vue'

  const sum = ref(0);

  function changeNum() {
    sum.value += 1;
  }

  watchEffect(() => {
    if (sum.value < 5) {
      console.log('num changed', sum.value)
    }
  })
</script>

<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
button {
  margin: 0 5px;
}
</style>

参考资料:

https://www.bilibili.com/video/BV1Za4y1r7KE?spm_id_from=333.788.player.switch\&vd_source=f839085517d2b7548b2939bfe214d466\&p=23



相关推荐
大只因bug2 分钟前
基于Springboot的在线考试与学习交流平台的设计与实现
java·spring boot·后端·学习·mysql·vue·在线考试与学习交流平台系统
我有一个object14 小时前
uniapp的IOS证书申请(测试和正式环境)及UDID配置流程
javascript·ios·uni-app·vue
猫猫村晨总15 小时前
vue3项目中引入阿里图标库
javascript·vue3·阿里图标
乐闻x19 小时前
Vue3中ref、toRef和toRefs之间有什么区别?
vue.js·vue
wqqqianqian1 天前
国产linux系统(银河麒麟,统信uos)使用 PageOffice 在线打开Word文件最简单集成代码
java·vue·word·在线·pageoffice·国产linux
暂时先用这个名字2 天前
vue开发的时候,目录名、文件名、函数名、变量名、数据库字段等命名规范
前端·数据库·vue.js·vue·开发·开发规范·命名规范
Tttian6222 天前
Vue中Axios和VantUI的基础使用
ajax·前端框架·npm·vue·1024程序员节
Roséa2 天前
antdesign vue 步骤条a-step按审核人员节点排序显示逻辑
前端框架·vue
aeoliancrazy3 天前
elementUI表达自定义校验,校验在v-for中
前端·elementui·vue·1024程序员节