广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >Vue中Computed和Watch的作用是什么
  • 261
分享到

Vue中Computed和Watch的作用是什么

2024-04-02 19:04:59 261人浏览 安东尼
摘要

本篇文章给大家分享的是有关Vue中Computed和Watch的作用是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。 Vue中的

本篇文章给大家分享的是有关Vue中Computed和Watch的作用是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

 Vue中的computed

Vue中的computed又叫做计算属性,Vue官网中给了下面这样一个示例。

模板中有一个message数据需要展示:

<template>   <div id="app">     {{message}}   </div> </template> <script> export default {   name: 'App',   data() {     return {       message: 'Hello'     }   } } </script>

假如此时有一个需求:对message进行反转并展示到模板中。

那最简单的实现方式就是直接在模板中做这样的转化:

<template>   <div id="app">     <p>{{message}}</p>     <p>{{message.split('').reverse().join('')}}</p>   </div> </template>

那这个时候,Vue官方告诉我们:过多的逻辑运算会让模板变得重且难以维护,而且这种转化无法复用,并指导我们使用计算属性-computed来实现这个需求。

export default {   name: 'App',   computed: {     reverseMessage: function(){       return this.message.split('').reverse().join('');     }   },   data() {     return {       message: 'Hello'     }   } }

在以上代码中我们定义了一个计算属性:reverseMessage,其值为一个函数并返回我们需要的结果。

之后在模板中就可以像使用message一样使用reverseMessage。

<template>   <div id="app">     <p>{{message}}</p>     <p>{{reverseMessage}}</p>   </div> </template>

那么此时有人肯定要说了,我用methods也能实现呀。确实使用methods也能实现此种需求,但是在这种情况下我们的计算属性相较于methods是有很大优势的,这个优势就是计算属性存在缓存

如果我们使用methods实现前面的需求,当message的反转结果有多个地方在使用,对应的methods函数会被调用多次,函数内部的逻辑也需要执行多次;而计算属性因为存在缓存,只要message数据未发生变化,则多次访问计算属性对应的函数只会执行一次。

<template>   <div id="app">     <p>{{message}}</p>     <p>第一次访问reverseMessage:{{reverseMessage}}</p>     <p>第二次访问reverseMessage:{{reverseMessage}}</p>     <p>第三次访问reverseMessage:{{reverseMessage}}</p>     <p>第四次访问reverseMessage:{{reverseMessage}}</p>   </div> </template>  <script> export default {   name: 'App',   computed: {     reverseMessage: function(value){       console.log(" I'm reverseMessage" )       return this.message.split('').reverse().join('');     }   },   data() {     return {       message: 'Hello'     }   } } </script>

运行项目,查看结果,会发现计算属性reverseMessage对应的函数只执行了一次。

Vue中Computed和Watch的作用是什么

3. Vue中的watchVue

中的watch又名为侦听属性,它主要用于侦听数据的变化,在数据发生变化的时候执行一些操作。

<template>   <div id="app">     <p>计数器:{{counter}}</p>     <el-button type="primary" @click="counter++">       Click     </el-button>   </div> </template>  <script> export default {   name: 'App',   data() {     return {       counter: 0     }   },   watch: {          counter: function(newValue, oldValue){       if(this.counter == 10){         this.counter = 0;       }     }   } } </script>

我们定义了一个侦听属性counter,该属性侦听的是Vue  data中定义counter数据,整个的逻辑就是点击按钮counter加1,当counter等于10的时候,将counter置为0。

上面的代码运行后的结果如下:

Vue中Computed和Watch的作用是什么

Vue官网很明确的建议我们这样使用watch侦听属性:当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

4.  computed和watch之间的抉择

看完以上两部分内容,关于Vue中computed和watch的基本用法算是掌握了。但实际上不止这些,所以接下来我们在来进阶学习一波。

这里我们还原Vue官网中的一个示例,示例实现的功能大致如下:

Vue中Computed和Watch的作用是什么

该功能可以简单的描述为:在firstName和lastName数据发生变化时,对fullName进行更新,其中fullName的值为firstName和lastName的拼接。

首先我们使用watch来实现该功能:watch侦听firstName和lastName,当这两个数据发生变化时更新fullName的值。

<template>   <div id="app">     <p>firstName: <el-input v-model="firstName" placeholder="请输入firstName"></el-input></p>     <p>lastName: <el-input v-model="lastName" placeholder="请输入lastName"></el-input></p>     <p>fullName: {{fullName}}</p>   </div> </template>  <script> export default {   name: 'App',   data() {     return {       firstName: '',       lastName: '',       fullName: '(空)'     }   },   // 使用watch实现   watch: {     firstName: function(newValue) {       this.fullName = newValue + ' ' + this.lastName;     },     lastName: function(newValue){       this.fullName = this.firstName + ' ' + newValue;     }   } } </script>

接着我们在使用computed来实现:定义计算属性fullName,将firstName和lastName的值进行拼接并返回。

<template>   <div id="app">     <p>firstName: <el-input v-model="firstName" placeholder="请输入firstName"></el-input></p>     <p>lastName: <el-input v-model="lastName" placeholder="请输入lastName"></el-input></p>     <p>fullName: {{fullName}}</p>   </div> </template>  <script> export default {   name: 'App',   data() {     return {       firstName: '',       lastName: ''     }   }   computed: {     fullName: function() {       return this.firstName + ' ' + this.lastName;     }   }  } </script>

我们发现computed和watch都可以实现这个功能,但是我们在对比一下这两种不同的实现方式:

// 使用computed实现 computed: {   fullName: function() {     return this.firstName + ' ' + this.lastName;   } },  // 使用watch实现 watch: {   firstName: function(newValue) {     this.fullName = newValue + ' ' + this.lastName;   },   lastName: function(newValue){     this.fullName = this.firstName + ' ' + newValue;   } }

对比之下很明显的会发现发现computed的实现方式更简洁高级。

所以在日常项目开发中,对于computed和watch的使用要慎重选择:

Vue中Computed和Watch的作用是什么

这两者选择和使用没有对错之分,只是希望能更好的使用,而不是滥用。

5. 计算属性进阶

接下来我们在对计算属性的内容进行进阶学习。

>>> 5.1 计算属性不能和Vue Data属性同名

在声明计算属性的时候,计算属性是不能和Vue Data中定义的属性同名,否则会出现错误:The computed property "xxxxx" is  already defined in data。

如果有阅读过Vue源码的同学对这个原因应该会比较清楚,Vue在初始化的时候会按照:initProps-> initMethods ->  initData -> initComputed ->  initWatch这样的顺序对数据进行初始化,并且会通过Object.definedProperty将数据定义到vm实例上,在这个过程中同名的属性会被后面的同名属性覆盖。

通过打印组件实例对象,可以很清楚的看到props、methods、data、computed会被定义到vm实例上。

>>> 5.2 计算属性的set函数

在前面代码示例中,我们的computed是这么实现的:

computed: {   reverseMessage: function(){     return this.message.split('').reverse().join('');   } },

这种写法实际上是给reverseMessage提供了一个get方法,所以上面的写法等同于:

computed: {   reverseMessage: {     // 计算属性的get方法     get: function(){       return this.message.split('').reverse().join('');     }   } },

除此之外,我们也可以给计算属性提供一个set方法:

computed: {   reverseMessage: {     // 计算属性的get方法     get: function(){       return this.message.split('').reverse().join('');     },     set: function(newValue){        // set方法的逻辑     }   } },

只有我们主动修改了计算属性的值,set方法才会被触发。

关于计算属性的set方法在实际的项目开发中暂时还没有遇到,不过经过一番思考,做出来下面这样一个示例:

Vue中Computed和Watch的作用是什么

这个示例是分钟和小时之间的一个转化,利用计算属性的set方法就能很好实现:

<template>   <div id="app">     <p>分钟<el-input v-model="minute" placeholder="请输入内容"></el-input></p>     <p>小时<el-input v-model="hours" placeholder="请输入内容"></el-input></p>   </div> </template>  <script> export default {   name: 'App',   data() {     return {       minute: 60,     }   },   computed: {     hours:{       get: function() {         return this.minute / 60;       },       set: function(newValue) {         this.minute = newValue * 60;       }     }   }  } </script>

>>> 5.3 计算属性的缓存

前面我们总结过计算属性存在缓存,并演示相关的示例。那计算属性的缓存是如何实现的呢?

关于计算属性的缓存这个知识点需要我们去阅读Vue的源码实现,所以我们一起来看看源码吧。

相信大家看到源码这个词就会有点胆战心惊,不过不用过分担心,文章写到这里的时候考虑到本篇文章的内容和侧重点,所以不会详细去解读计算属性的源码,着重学习计算属性的缓存实现,并且点到为止。

那如果你没有仔细解读过Vue的响应式原理,那建议忽略这一节的内容,等对源码中的响应式有一定了解之后在来看这一节的内容会更容易理解。(我自己之前也写过的一篇相关文章:1W字长文+多图,带你了解vue2.x的双向数据绑定源码实现,点击文末阅读原文即可查看)

关于计算属性的入口源代码如下:

 export function initState (vm: Component) {   // ......省略......   const opts = vm.$options   // ......省略......   if (opts.computed) initComputed(vm, opts.computed)   // ......省略                                                                       ...... }

接着我们来看看initComputed:

 function initComputed (vm: Component, computed: Object) {        const watchers = vm._computedWatchers = Object.create(null)     // 遍历计算属性   for (const key in computed) {     const userDef = computed[key]          const getter = typeof userDef === 'function' ? userDef : userDef.get              watchers[key] = new Watcher(       vm,       getter || noop,       noop,       computedWatcherOptions     )     // 函数调用     defineComputed(vm, key, userDef)   } }

在initComputed这个函数中,主要是遍历计算属性,然后在遍历的过程中做了下面两件事:

  • 第一件:为计算属性创建watcher,即new Watcher

  • 第二件:调用defineComputed方法

那首先我们先来看看new Watcher都做了什么。

为了方便大家看清楚new Watcher的作用,我将Watcher的源码进行了简化,保留了一些比较重要的代码。

同时代码中重要的部分都添加了注释,有些注释描述的可能有点重复或者啰嗦,但主要是想以这种重复的方式让大家可以反复琢磨并理解源码中的内容,方便后续的理解  ~

 export default class Watcher {   constructor (     vm: Component,     expOrFn: string | Function,     cb: Function,     options?: ?Object,   ) {     // vm为组件实例     this.vm = vm       // expOrFn在new Watcher时传递的参数为计算属性的get方法     // 将计算属性的get方法赋值给watcher的getter属性     this.getter = expOrFn     // cb为noop:export function noop (a?: any, b?: any, c?: any) {}     this.cb = cb       // option在new Watcher传递的参数值为{lazy: true}      // !!操作符即将options.lazy强转为boolean类型     // 赋值之后this.lazy的值为true     this.lazy = !!options.lazy      // 赋值之后this.dirty的值true     this.dirty = this.lazy                this.value = this.lazy ? undefined : this.get()   }   get () {      const vm = this.vm          value = this.getter.call(vm, vm)     return value   }   evaluate () {           this.value = this.get()     this.dirty = false   } }

看了这个简化版的Watcher以后,想必我们已经很清楚的知道了Watcher类的实现。

那接下来就是关于缓存的重点了,也就是遍历计算属性做的第二件事:调用defineComputed函数:

 export function defineComputed (   target: any,   key: string,   userDef: Object | Function ) {      // ......暂时省略有关sharedPropertyDefinition的代码逻辑......         Object.defineProperty(target, key, sharedPropertyDefinition) }

defineComputed方法最核心也只有一行代码,也就是使用Object.defineProperty将计算属性变得可观测。

那么接下来我们的关注点就是调用Object.defineProperty函数时传递的第三个参数:sharedPropertyDefinition。

sharedPropertyDefinition是定义在当前文件中的一个对象,默认值如下:

const sharedPropertyDefinition = {   enumerable: true,   configurable: true,   get: noop,   set: noop }

前面贴出来的defineComputed源码中,我注释说明省略了一段有关sharedPropertyDefinition的代码逻辑,那省略的这段源代码就不展示了,它的主要作用就是在对sharedPropertyDefinition.get和sharedPropertyDefinition.set进行重写,重写之后sharedPropertyDefinition的值为:

const sharedPropertyDefinition = {   enumerable: true,   configurable: true,   get: function(){       // 获取计算属性对应的watcher实例       const watcher = this._computedWatchers && this._computedWatchers[key]       if (watcher) {         if (watcher.dirty) {           watcher.evaluate()         }         if (Dep.target) {           watcher.depend()         }         return watcher.value       }     }   },   // set对应的值这里写的是noop   // 但是我们要知道set真正的值是我们为计算属性提供的set函数   // 千万不要理解错了哦    set: noop,   }

那sharedPropertyDefinition.get函数的逻辑已经非常的清晰了,同时它的逻辑就是计算属性缓存实现的关键逻辑:在sharedPropertyDefinition.get函数中,先获取到计算属性对应的watcher实例;然后判断watcher.dirty的值,如果该值为false,则直接返回watcher.value;否则调用watcher.evaluate()重新获取计算属性的值。

关于计算属性缓存的源码分析就到这里,相信大家对计算属性的缓存实现已经有了一定的认识。不过仅仅是了解这些还不够,我们应该去通读计算属性的完整源码实现,才能对计算属性有一个更通透的认识。

6. 侦听属性进阶

>>> 6.1 handler

前面我们是这样实现侦听属性的:

watch: {   counter: function(newValue, oldValue){     if(this.counter == 10){       this.counter = 0;     }   } }

那上面的这种写法等同于给counter提供一个handler函数:

watch: {   counter: {     handler: function(newValue, oldValue){       if(this.counter == 10){         this.counter = 0;       }     }   } }

>>> 6.2 immediate

正常情况下,侦听属性提供的函数是不会立即执行的,只有在对应的vue data发生变化时,侦听属性对应的函数才会执行。

那如果我们需要侦听属性对应的函数立即执行一次,就可以给侦听属性提供一个immediate选项,并设置其值为true。

watch: {   counter: {     handler: function(newValue, oldValue){       if(this.counter == 10){         this.counter = 0;       }     },     immediate: true   } }

>>> 6.3 deep

如果我们对一个对象类型的vue data进行侦听,当这个对象内的属性发生变化时,默认是不会触发侦听函数的。

<template>   <div id="app">     <p><el-input v-model="person.name" placeholder="请输入姓名"></el-input></p>     <p><el-input v-model="person.age" placeholder="请输入年龄"></el-input></p>   </div> </template> <script> export default {   name: 'App',   data() {     return {       person: {         name: 'jack',         age: 20       }     }   },   watch: {     person: function(newValue){       console.log(newValue.name + ' ' + newValue.age);     }   } } </script>

监听对象类型的数据,侦听函数没有触发:

Vue中Computed和Watch的作用是什么

通过给侦听属性提供deep: true就可以侦听到对象内部属性的变化:

watch: {   person: {     handler: function(newValue){       console.log(newValue.name + ' ' + newValue.age);     },     deep: true   } }
Vue中Computed和Watch的作用是什么

不过仔细观察上面的示例会发现这种方式去监听Object类型的数据,Object数据内部任一属性发生变化都会触发侦听函数,那如果我们想单独侦听对象中的某个属性,可以使用下面这样的方式:

watch: {   'person.name': function(newValue, oldValue){       // 逻辑    } }

以上就是Vue中Computed和Watch的作用是什么,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注编程网JavaScript频道。

--结束END--

本文标题: Vue中Computed和Watch的作用是什么

本文链接: https://www.lsjlt.com/news/71999.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Vue中Computed和Watch的作用是什么
    本篇文章给大家分享的是有关Vue中Computed和Watch的作用是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。 Vue中的...
    99+
    2022-10-19
  • Vue中的watch、watch和computed的区别是什么
    本文小编为大家详细介绍“Vue中的watch、watch和computed的区别是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue中的watch、watch和computed的区别是什么”文章能帮助大家解决疑惑,下面跟着小编的思路...
    99+
    2023-07-02
  • Vue中的watch是什么以及watch和computed的区别
    目录一、watch是什么?二、应用基本用法三、Watch和computed的区别computed和watch的综合运用实例需求:实现代码(helloworld.vue实现代码)一、w...
    99+
    2022-11-13
  • Vue中的computed和watch的区别是什么
    Vue中的computed和watch的区别是什么,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。下面带大家认识Vue中的computed 和 watch,介绍一下compu...
    99+
    2023-06-22
  • vue中computed 和 watch有什么区别
    vue中computed 和 watch有什么区别,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。一、computed 和 wa...
    99+
    2022-10-19
  • 怎么在vue中使用 Watch和Computed
    本篇文章给大家分享的是有关怎么在vue中使用 Watch和Computed,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。01. 监听器watch(1)作用watch:用于监听d...
    99+
    2023-06-15
  • Vue中的Computed与watch怎么用
    这篇“Vue中的Computed与watch怎么用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Vue中的Computed与...
    99+
    2023-06-30
  • vue Watch和Computed的使用总结
    目录01. 监听器watch (1)作用 (2)属性和方法 (3)监听对象 (4)监听数组 02. 计算属性computed (1)计算属性的set方法 (2)区别 (3)使用场景 ...
    99+
    2022-11-12
  • vue.js中methods watch和computed的区别是什么
    这篇文章给大家介绍vue.js中methods watch和computed的区别是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。一、作用机制上computed\watch:watch和computed都是以Vue...
    99+
    2023-06-20
  • Vue中的computed和watch用法及区别
    目录vue computed 是如何实现的computed demovue的watch是如何实现的watch demovue computed 是如何实现的 Vue 的 comput...
    99+
    2023-05-17
    Vue computed和watch Vue computed Vue watch
  • Vue中computed和watch的区别小结
    目录一、Vue中computed和watch的区别二、computed计算属性三、区别总结区别:计算属性computed支持缓存,只有依赖数据发生改变,才会重新进行计算;不支持异步,...
    99+
    2022-12-10
    Vue中computed和watch的区别 Vue中computed和watch异同
  • vue中computed和watch的区别和运用场景
    这篇文章主要为大家展示了“vue中computed和watch的区别和运用场景”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“vue中computed和watch...
    99+
    2022-10-19
  • 分析 Vue 中的 computed 和 watch 的区别
    目录一、computed介绍1.1、get 和 set 用法 1.2、计算属性缓存二、watch介绍三、两者区别3.1、对于 computed3.2、对于 watch四、应...
    99+
    2022-11-12
  • Vue 中的 computed 和 watch 的区别详解
    目录computed注意应用场景watch总结computed computed 看上去是方法,但是实际上是计算属性,它会根据你所依赖的数据动态显示新的计算结果。计算结果会被缓存,c...
    99+
    2022-11-13
  • Vue中computed和watch的区别有哪些
    小编给大家分享一下Vue中computed和watch的区别有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!概述我们在 Vue 项目中多多少少都会有用到 co...
    99+
    2023-06-15
  • Vue中computed属性和watch,methods的区别
    目录computedwatchmethods归纳三者不同点1、methods2、computed3、watch在Vue中,computed、watch和methods是处理响应式数据...
    99+
    2023-05-19
    Vue computed属性 watch methods
  • vue中watch和computed能监听到数据改变的原因是什么
    这篇文章主要为大家展示了“vue中watch和computed能监听到数据改变的原因是什么”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“vue中watch和co...
    99+
    2022-10-19
  • vue3中的watch和computed怎么使用
    2.监听 ref 数据2.1监听一个 ref 数据<template> <p>{{ age }}</p> <button @click="age++">click&...
    99+
    2023-05-21
    Vue3 watch computed
  • 如何理解Vue中computed和watch的区别
    目录概述computed 计算属性watch 监听属性总结概述 我们在 Vue 项目中多多少少都会有用到 computed 和 watch,这两个看似都能实现对数据的监听,但还是有区...
    99+
    2022-11-12
  • vue中computed和watch的使用实例代码解析
    需求: 1.点击按钮实现天气的切换;2.用watch进行监视天气产生变化的数据; 实现代码(helloworld.vue实现代码): <template> <...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作