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



相关推荐
咚咚咚小柒10 小时前
【前端】LangChain.js学习
前端·javascript·人工智能·typescript·langchain·vue·ai编程
AI源码2 天前
巨峰影视影院
vue3
RuoyiOffice2 天前
UniApp企业办公:把审批、客户和项目装进手机,能做些什么?
spring boot·vue3·uniapp·crm·flowable·移动办公·企业应用
悟道书生2 天前
若依 RBAC 权限控制学习笔记
java·网络·笔记·sql·学习·vue
mewowaBc2 天前
使用Pinia持久化存储实现用户认证系统
vue·pinia·用户认证系统
RuoyiOffice3 天前
SpringBoot OA推荐:面向信创选型,看看这套企业协同平台
spring boot·vue3·信创·flowable·企业协同·ruoyi office·oa选型
周厉3 天前
WebSocket 使用场景与实现方法:Java + Vue3 全栈实战
java·websocket·vue3·websocket双向通讯
gc_22993 天前
使用VS Code终端创建Vue项目报错:“npm : 无法加载文件 ...\npm.ps1,因为在此系统上禁止运行脚本”
vue·vs code
小阿鑫4 天前
尤雨溪 : Vue 4 已经在规划中了!
vue·vite·vite+·程序员海军·vue4
红红谈说4 天前
同一套产品两个技术栈,双版本前端工程差异怎么收敛?
前端·uni-app·vue3·前后端分离·双版本维护·接口约定