简记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



相关推荐
天下无贼!1 天前
【轮播图】H5端轮播图、横向滑动、划屏效果实现方案——Vue3+CSS position/CSS scroller
javascript·css·vue.js·vue
安琪吖1 天前
微前端:qiankun框架在开发中遇到的问题
前端·vue·element-ui
JIngJaneIL1 天前
家常菜点餐|基于java和小程序的家庭大厨家常菜点餐系统设计与实现(源码+数据库+文档)
java·数据库·小程序·vue·论文·毕设·家常菜点餐系统
飞翔的佩奇2 天前
基于SpringBoot+MyBatis+MySQL+VUE实现的房屋交易平台管理系统(附源码+数据库+毕业论文+部署教程+配套软件)
数据库·spring boot·mysql·vue·毕业设计·mybatis·房屋交易平台
YL雷子2 天前
纯前端使用ExcelJS插件导出Excel
前端·vue·excel
aiguangyuan2 天前
Vue 服务端渲染 Nuxt 使用详解
vue·前端开发·ssr
青柠代码录3 天前
【ElementPlus】深入探索ElementPlus:前端界面的全能组件库
前端·vue3·elementplus
喜欢敲代码的程序员4 天前
SpringBoot+Mybatis+MySQL+Vue+ElementUI前后端分离版:日志管理(四)集成Spring Security
spring boot·mysql·spring·vue·mybatis
netho04 天前
nuxt3: trpc-nuxt和sqlite导致的503错误
数据库·sqlite·vue·nuxt
周航宇JoeZhou5 天前
JP3-3-MyClub后台后端(二)
java·mysql·vue·ssm·springboot·项目·myclub