当前位置: 首页 > news >正文

【前端学习指南】Vue computed 计算属性 watch 监听器

🍭 Hello,我是爱吃糖的范同学 

        🔴 想把自己学习技术的经历和一些总结分享给大家!

        🔴 通过这样的方式记录自己成长,同时沉淀自己的技术,我会把所有额外的时间和经历投放到CSDN和公众号(💥公号名:AIRC Team💥,欢迎关注,为大家准备了很多有关编程学习资料)文章的撰写。

        🔴 希望能通过这样的方式让大家认识我,和我一起学习编程,共同进步!😃

        希望能和大家一起进步和成长!坚持热爱!🎉🎉🎉


目录

✏️ computed 计算属性:

✏️  watch 监听器:

1.定义一个watch监听器:

2.immediate 选项:

3.deep 选项:

4.监听对象单个属性变化:

✏️  计算属性与监听器对比 :

1.适用场景

2. 特性对比

2.1 计算属性

2.2 监听器

3.何时选择计算属性,何时选择监听器

✏️ 写在最后:

✏️ 往期文章: 


✏️ computed 计算属性:

        计算属性本质上就是一个 function 函数,它可以实时监听 data 中的数据变化,并 return 一个计算后的新值提供给组件,组件会对这个新值进行 DOM 渲染。

1.声明一个计算属性:

        计算属性需要以 function 函数的形式声明到组件的 computed 选项中。

<template><div><h1>{{ fullName }}</h1><input v-model="firstName" placeholder="Enter first name"><input v-model="lastName" placeholder="Enter last name"></div>
</template><script>
export default {data() {return {firstName: '',lastName: ''};},computed: {fullName() {return `${this.firstName} ${this.lastName}`;}}
};
</script><style scoped>
/* Optional CSS styles */
</style>

         data 中定义了 firstName 和 lastName,它们会绑定到两个输入框的值。computed 中定义了一个计算属性 fullName,它会根据 firstName 和 lastName 的值动态计算并返回一个拼接后的全名。当你输入名字时,fullName 会自动更新并显示在页面上。

        计算属性是基于依赖的响应式数据来缓存的,只有相关的数据发生变化时,它们才会重新计算,从而提高性能。

如果是使用的Vue3 的 setup 语法糖怎么进行声明捏???

        在 vue3 中,computed 可以在 setup 函数里实现。除了写法不一样,功能上与 vue2 中的 computed 是一致

  • 只有 getter 时,传入一个回调函数。

  • 有 getter 和 setter时,传入一个对象,有 get 和 set 两个属性方法。

  • 需要将处理后的值返回作为该计算属性的值。

在 setup 里使用 computed 的三种方式:

(1)直接在 setup 里使用 computed 函数;

<template><div>{{ fullName }}</div>
</template><script>import { ref, computed } from 'vue'export default {setup() {const firstName = ref('hello')const lastName = ref('world')const fullName = computed(() => {return firstName.value + '-·-' + lastName.value})return {firstName,lastName,fullName}}}
</script>

(2)通过 defineComponent 函数在 setup 里使用 computed 函数

        defineComponent 函数是 vue3 的语法糖:

        PS:defineComponent 函数支持 TS 的 “参数类型推断”(如果你使用的是 vue3 + TS,那么使用 defineComponent 将会更友好。)

<template><div>{{ fullName }}</div>
</template><script>import { defineComponent, ref, computed } from 'vue'export default defineComponent({setup() {const firstName = ref('hello')const lastName = ref('world')const fullName = computed(() => {return firstName.value + '-·-' + lastName.value})return {firstName,lastName,fullName}}})
</script>

(3)在 <script setup> 里使用 computed 函数

        <script setup> 是 vue3 的新的语法糖,之前的组合 API 相比:

  • 之前的组合 API 必须返回 return,使用 <script setup> 后就不必了。

  • 有更好的运行时性能。

<template><div>{{ fullName }}</div>
</template><script setup>import { ref, computed } from 'vue'const firstName = ref('hello')const lastName = ref('world')const fullName = computed(() => {return firstName.value + '-·-' + lastName.value})
</script>

在 setup 里的 computed 的 getter 和 setter:

        当 computed 有 getter 和 setter 时,需要传入一个对象而不是一个函数作为 computed 的参数,然后在 computed 中实现 get 和 set 两个属性方法。

<template><div> firstName: {{ firstName }} </div><div> lastName: {{ lastName }} </div><div> fullName: {{ fullName }} </div>
</template><script>import { reactive, toRefs, computed } from 'vue'export default {setup() {const user = reactive({firstName: 'hello',lastName: 'world'})const fullName = computed({get() {return user.firstName + '-·-' + user.lastName},set(val) {const nameList = val.split('-·-')user.firstName = nameList[0]user.lastName = nameList[1]}})return {...toRefs(user),fullName}}}
</script>

2.计算属性与方法对比:

        计算属性会对计算执行结果进行缓存,只有计算属性的依赖项(原始数据来源)发生变化时,才会重新计算。否则,都是直接获取当前缓存的计算结果。而无需重新执行计算逻辑。相对于方法来说,计算属性的性能比方法更好。

  • 计算属性和方法的调用方式不同: 计算属性是通过对应名称直接访问的,而方法需要在模板中使用 v-on 指令或者 @ 符号进行调用。

  • 计算属性可以缓存结果,而方法不能: 计算属性的值会被缓存起来,只有在它所依赖的响应式数据变化时才会重新计算。而方法每次调用都要重新计算,无法被缓存。

  • 计算属性应该用于简单的计算,而方法用于复杂逻辑的处理: 如果需要对数据进行一些简单的计算或过滤,可以使用计算属性,因为它们比方法更高效。而如果需要进行一些复杂的逻辑处理,应该使用方法。


✏️  watch 监听器:

        watch 监听器允许开发者监视数据的变化,从而针对数据的变化进行特定的操作。例如可以监听输入框的输入信息,发起 Ajax 请求返回和输入内容相关的搜索信息。

1.定义一个watch监听器:

        message 被监听,一旦它的值发生变化,watch 会调用对应的回调函数,newValue 是新值,oldValue 是旧值。可以在这个回调中做其他逻辑操作,比如发起异步请求、验证数据、或者进行其他逻辑处理。

        这种方式适用于当你需要在数据变化时执行一些操作,且该操作不适合放在 computed 中的情况。

<template><div><input v-model="message" placeholder="Enter a message"><p>Message: {{ message }}</p><p>Message length: {{ messageLength }}</p></div>
</template><script>
export default {data() {return {message: ''};},computed: {messageLength() {return this.message.length;}},watch: {// 监听 message 的变化message(newValue, oldValue) {console.log(`Message changed from "${oldValue}" to "${newValue}"`);// 这里可以加入一些逻辑,比如发送请求或者做其他操作}}
};
</script><style scoped>
/* Optional CSS styles */
</style>

   data 中定义了 message,它会绑定到一个输入框,允许用户输入文本。computed 中定义了 messageLength,计算并返回 message 的长度。watch 监听器监听 message 的变化。当用户输入时,watch 会触发,打印出 message 之前和之后的值。

在 setup 语法糖中使用监听器:

        使用 watch 来监听 message 的变化。当 message 的值发生变化时,回调函数会触发,打印出旧值和新值。

        设置 immediate: true,使得监听器在组件创建时立即触发一次,打印出 message 的初始值变化。

        返回值:在 setup 中返回了 message 和 messageLength,这些值可以在模板中使用。

<template><div><input v-model="message" placeholder="Enter a message"><p>Message: {{ message }}</p><p>Message length: {{ messageLength }}</p></div>
</template><script>
import { ref, watch } from 'vue';export default {setup() {// 定义响应式数据const message = ref('Hello, Vue!');// 计算属性的实现const messageLength = computed(() => message.value.length);// 使用 watch 监听 `message` 变化,immediate 设置为 truewatch(message,(newValue, oldValue) => {console.log(`Message changed from "${oldValue}" to "${newValue}"`);},{ immediate: true }  // 初始化时立即触发);// 返回需要在模板中使用的数据和方法return {message,messageLength};}
};
</script><style scoped>
/* Optional CSS styles */
</style>

2.immediate 选项:

        默认情况下,组件在初次加载完毕后不会调用 watch 监听器。如果希望 watch 监听器能够立即被调用,则需要使用 immediate 选项。

<template><div><input v-model="message" placeholder="Enter a message"><p>Message: {{ message }}</p><p>Message length: {{ messageLength }}</p></div>
</template><script>
export default {data() {return {message: 'Hello, Vue!'};},computed: {messageLength() {return this.message.length;}},watch: {// 监听 message 的变化,immediate 设置为 truemessage: {handler(newValue, oldValue) {console.log(`Message changed from "${oldValue}" to "${newValue}"`);},immediate: true  // 在初始化时立即触发}}
};
</script><style scoped>
/* Optional CSS styles */
</style>

    handler 是实际的监听函数,它会打印出 message 的变化。immediate: true 会使得监听器在组件创建时就立即执行一次,而不仅仅是在 message 发生变化时。

3.deep 选项:

        当 watch 监听的是一个对象,如果对象的属性值发生了变化,上面的配置情况下是无法监听到变化的。此时需要使用 deep 选项。

<template><div><input v-model="user.name" placeholder="Enter your name" /><input v-model="user.age" placeholder="Enter your age" /><p>User Info: {{ user.name }} - {{ user.age }}</p></div>
</template><script>
import { ref, watch } from 'vue';export default {setup() {// 定义一个包含嵌套属性的响应式对象const user = ref({name: 'John Doe',age: 30});// 使用 deep 选项来监听对象的深层变化watch(user,(newValue, oldValue) => {console.log('User info changed:', newValue);},{ deep: true }  // 开启深度监听);return {user};}
};
</script><style scoped>
/* Optional CSS styles */
</style>

        响应式对象user 是一个包含 name 和 age 属性的对象,通过 ref 包装为响应式对象。

  watch 使用:我们使用 watch 来监听 user 对象的变化,并设置了 { deep: true } 选项,意味着如果 user 对象的任何嵌套属性发生变化,监听器都会被触发。

        回调函数:每次 user 对象发生深层次变化时(比如修改了 name 或 age),回调函数就会打印新的 user 对象。

为什么使用 deep

  • 浅层监听:默认情况下,watch 只会监听对象或数组的引用变化。例如,如果你直接修改了 user.name 的值,watch 会被触发。

  • 深层监听:使用 deep: true 选项后,即使修改了嵌套的属性(例如 user.name 或 user.age),watch 也会检测到变化并触发回调。这对于复杂的数据结构非常有用,特别是当你需要监听嵌套的对象或数组时。

注意事项:

  • 开启 deep 选项会带来一定的性能开销,尤其是在对象或数组较大时,因为它需要对整个对象或数组进行递归遍历和监控。因此,在使用时要谨慎,避免不必要的性能损失。

  • 适合用于需要对深层次数据进行监控的场景,比如表单数据、复杂对象等。

4.监听对象单个属性变化:

        在使用 deep 选项后,会对整个对象中的所有属性值的变化进行监听,但是处于某种场景下,只希望对对象中某个属性进行监听,此时可以按照如下规则进行定义 watch 监听器:

<template><div><input v-model="user.name" placeholder="Enter your name" /><p>User Name: {{ user.name }}</p></div>
</template><script>
export default {data() {return {user: {name: 'John Doe',age: 30}};},watch: {// 监听 user.name 属性变化'user.name': function (newValue, oldValue) {console.log(`User name changed from "${oldValue}" to "${newValue}"`);}}
};
</script><style scoped>
/* Optional CSS styles */
</style>

        如果你想监听多个属性,并且希望在属性变化时做统一的处理,可以使用 watch对象形式,将多个属性的监听逻辑写在一个 handler 中。例如:

<script>
export default {data() {return {user: {name: 'John Doe',age: 30}};},watch: {// 监听 user 对象中的多个属性变化'user': {handler(newUser, oldUser) {if (newUser.name !== oldUser.name) {console.log(`Name changed: ${oldUser.name} -> ${newUser.name}`);}if (newUser.age !== oldUser.age) {console.log(`Age changed: ${oldUser.age} -> ${newUser.age}`);}},deep: true  // 深度监听整个 user 对象的变化}}
};
</script>

✏️  计算属性与监听器对比 :

        计算属性(computed)和监听器(watch)是 Vue 中用于处理数据变化的两种常用方式。它们各自有不同的用途和特性,理解它们的差异能帮助你在开发中做出更合适的选择。

  • 计算属性(computed):

    • 用于基于已有数据计算派生数据(例如,多个数据项的组合结果)。

    • 计算属性会缓存计算结果,只有当其依赖的数据变化时才会重新计算。这使得它们在性能上更加高效,避免不必要的计算。

    • 计算属性是 惰性求值,即只有在它们被访问时才会计算,并且会缓存直到依赖项发生变化。

  • 监听器(watch):

    • 用于在数据变化时执行 异步操作 或执行副作用(比如向服务器发起请求)。

    • 监听器可以监听 某个数据属性的变化,并在变化时执行指定的回调函数。

    • 监听器是 立即执行 的,即数据变化后会立即触发回调函数。

1.适用场景

  • 计算属性:当你需要根据一个或多个数据属性的值进行计算,且计算结果依赖的数据不经常变化时,使用计算属性更合适。它主要用于:

    • 从已有数据计算出新的值(例如,格式化日期、计算总金额等)。

    • 需要缓存计算结果,避免重复计算的场景。

  • 监听器:当你需要执行异步操作、或者某些副作用操作时(如发起 HTTP 请求、操作 DOM 或者调用外部 API),使用监听器更为合适。它适用于:

    • 监控数据变化并执行副作用(例如,当某个输入框的值变化时触发表单提交)。

    • 需要对某些数据变化进行处理,而不仅仅是计算派生数据。

2. 特性对比

特性

计算属性 (computed)

监听器 (watch)

主要用途

计算派生数据,避免重复计算。

监听数据变化并执行副作用(如异步操作)。

缓存

会缓存计算结果,只有依赖的数据变化时才重新计算。

不缓存,每次数据变化都会执行回调函数。

执行时机

在模板渲染时或者访问时计算。

在数据变化时立即执行回调函数。

返回值

必须返回一个值,这个值通常用在模板中或其他计算属性中。

无返回值,通常用来触发副作用(如发起请求、修改 DOM)。

异步操作

不适合处理异步操作。

非常适合处理异步操作。

复杂计算

适合简单的、基于已有数据的计算。

不适合做复杂的计算,更多用于处理副作用。

性能

性能较好,因其计算结果会被缓存。

每次数据变化都会执行,可能影响性能。

2.1 计算属性

<template><div><p>{{ fullName }}</p></div>
</template><script>
export default {data() {return {firstName: 'John',lastName: 'Doe'};},computed: {fullName() {// 计算并返回 fullName,只会在 firstName 或 lastName 改变时重新计算return this.firstName + ' ' + this.lastName;}}
};
</script>
  • 解释fullName 是一个计算属性,它基于 firstName 和 lastName 来计算,并且会在这两个数据发生变化时重新计算。计算属性会缓存计算结果,避免多次计算。

2.2 监听器

<template><div><input v-model="name" placeholder="Enter your name"></div>
</template><script>
export default {data() {return {name: ''};},watch: {// 监听 name 的变化,并在变化时执行回调函数name(newName) {console.log('Name changed to: ' + newName);// 可以在这里执行异步操作,比如发起 HTTP 请求等}}
};
</script>
  • 解释watch 监听 name 的变化,当 name 的值发生变化时,会执行指定的回调函数。在这个例子中,我们简单地打印了新值,但也可以在回调中执行更复杂的操作,比如向服务器发送请求。

3.何时选择计算属性,何时选择监听器

选择计算属性

  • 当你需要在模板中显示一个基于其他数据的计算值时。

  • 当你需要避免重复计算时(缓存计算结果)。

  • 当你不需要执行副作用(例如异步操作或修改外部状态)时。

选择监听器

  • 当你需要在数据变化时执行副作用操作时(如发送 HTTP 请求、修改 DOM、触发动画等)。

  • 当你需要在数据变化后进行复杂的操作,而不仅仅是计算派生数据时。

  • 当你需要监听的数据是动态变化的,不适合缓存时。

组合使用:

        有时,你可能需要同时使用计算属性和监听器。例如,可以使用计算属性来生成数据,使用监听器来处理外部副作用。

<template><div><input v-model="name" placeholder="Enter your name"><p>{{ greeting }}</p></div>
</template><script>
export default {data() {return {name: ''};},computed: {// 使用计算属性生成问候语greeting() {return this.name ? `Hello, ${this.name}!` : 'Hello!';}},watch: {// 监听 name 的变化,触发异步请求name(newName) {if (newName) {this.fetchGreeting(newName);}}},methods: {async fetchGreeting(name) {// 假设这里发起了一个异步请求console.log(`Fetching greeting for ${name}...`);}}
};
</script>


✏️ 写在最后:

        学习是通往未来的桥梁,是打开世界大门的钥匙。每一步的坚持,都是向梦想迈进的一小步。即使今天的努力看不见回报,明天的你会感谢今天的自己。记住,每一个挑战都是成长的机会,每一次进步都是成功的积累。别怕慢,只有不前行才会停滞。相信自己的潜力,勇敢追求知识,你将会看到一个不一样的、更强大的自己!


✏️ 往期文章: 

2024年还在问前端怎么学?一份前端学习指南_web前端怎么学习人工智能-CSDN博客

【前端学习指南】基础开发环境搭建_前端项目搭建环境-CSDN博客

【前端学习指南】开启 Vue 的学习之旅_前端vue 学习之旅-CSDN博客

【前端学习指南】第一站 Vue 生命周期初探_vue 前端学习-CSDN博客

【前端学习指南】第二站 Vue 工程化开发-CSDN博客

【前端学习指南】第三站 Vue 组件之间通信-CSDN博客

【前端学习指南·番外篇】Node.js 安装及环境配置_node前端运行环境-CSDN博客


http://www.mrgr.cn/news/74677.html

相关文章:

  • C++编程:利用环形缓冲区优化 TCP 发送流程,避免 Short Write 问题
  • vue2和vue3的区别详解
  • 【测试框架篇】单元测试框架pytest(1):环境安装和配置
  • 【FreeRL】MAPPO的简单复现
  • 1 图的搜索 奇偶剪枝
  • 为什么卷积现在不火了:CNN研究热度降温的深层原因分析
  • 2024 ECCV | DualDn: 通过可微ISP进行双域去噪
  • 2024-在Gentoo claculate Linux中设置中文支持
  • 【云原生开发】K8S多集群管理系统成果展示
  • WinCC Professional S5Time及Time数据显示
  • Ubuntu20.04.3.LTS安装ftp
  • .NET 9中数据集合类型及其性能比较与应用场景分析
  • 管家婆财贸ERP BB092.物配任务工作台凭证引入
  • MySQL索引创建原则总结
  • 现代网络安全:关键技术与实战策略
  • 利用 React 构建现代化 Web 应用的核心实践
  • BFS 算法专题(三):BFS 解决边权为 1 的最短路问题
  • PostgreSQL 一键安装部署脚本化
  • 【算法】【优选算法】前缀和(上)
  • SQLI LABS | Less-45 POST-Error Based-String-Stacked-Bilnd
  • Python防检测之鼠标移动轨迹算法
  • 英语中常用的两者及以上的词表示,并且比较它们
  • Bootstrap 5 轮播
  • Rust 数据类型
  • 鸿蒙北向开发环境安装指南
  • 后台管理系统的通用权限解决方案(十四)基于JWT实现登录功能