vue的computed与watch (详细讲解区别和用法)

计算属性computed

什么是计算属性呢?

官方并没有给出直接的概念解释;

而是说:对于任何包含响应式数据的复杂逻辑,你都应该使用计算属性

计算属性将被混入到组件实例中。所有 getter 和 setter 的 this 上下文自动地绑定为组件实例;

我们可以有三种实现思路:

  • 思路一:在模板语法中直接使用表达式;

过于复杂的逻辑判断

重复多次的使用,没有缓存

  • 思路二:使用method对逻辑进行抽取;

我们事实上先显示的是一个结果,但是都变成了一种方法的调用;

多次使用方法的时候,没有缓存,也需要多次计算;

  • 思路三:使用计算属性computed;
<template id="my-app">
    <h2>{{ fullName }}</h2>
  </template>

  <script src="../js/vue.js"></script>
  <script>
    const App = {
      template: '#my-app',
      data() {
        return {
          firstName: "Kobe",
          lastName: "Bryant",
        }
      },
      computed: {
        fullName() {
          return this.firstName + this.lastName;
        },
    }

    Vue.createApp(App).mount('#app');
  </script>

conputed与method的差异

<div id="app"></div>

  <template id="my-app">
    <!-- 1.使用methods -->
    <h2>{{getResult()}}</h2>
    <h2>{{getResult()}}</h2>
    <h2>{{getResult()}}</h2>

    <!-- 2.使用computed -->
    <h2>{{result}}</h2>
    <h2>{{result}}</h2>
    <h2>{{result}}</h2>
  </template>

  <script src="../js/vue.js"></script>
  <script>
    const App = {
      template: '#my-app',
      data() {
        return {
          score: 90
        }
      },
      computed: {
        result() {
          console.log("调用了计算属性result的getter");
          return this.score >= 60 ? "及格": "不及格";
        }
      },
   
      methods: {
        getResult() {
          console.log("调用了getResult方法");
          return this.score >= 60 ? "及格": "不及格";
        }
      }
    }

    Vue.createApp(App).mount('#app');
  </script>
computed值使用了一次,之后都是使用的缓存
  • 这是因为计算属性会基于它们的依赖关系进行缓存;
  • 在数据不发生变化时,计算属性是不需要重新计算的;
  • 但是如果依赖的数据发生变化,在使用时,计算属性依然会重新进行计算;
method每次的使用都重新调用的方法,重复执行

computed属性的setter和getter

计算属性在大多数情况下,只需要一个getter方法即可,所以我们会将计算属性直接写成一个函数。

{ [key: string]: Function | { get: Function, set: Function } }

 <template id="my-app">
    <h2>{{fullName}}</h2>
    <button @click="setNewName">设置新名字</button>
  </template>

  <script src="../js/vue.js"></script>
  <script>
    const App = {
      template: '#my-app',
      data() {
        return {
          firstName: "Kobe",
          lastName: "Bryant"
        }
      },
      computed: {
        fullName: {
          get() {
            return this.firstName + " " + this.lastName;
          },
          set(value) {
            const names = value.split(" ");
            this.firstName = names[0];
            this.lastName = names[1];
          }
        }
      },
      methods: {
        setNewName() {
          this.fullName = "coder why";
        }
      }
    }

    Vue.createApp(App).mount('#app');
  </script>

侦听器watch

类型:{ [key: string]: string | Function | Object | Array}

什么是侦听器呢?

  • 开发中我们在data返回的对象中定义了数据,这个数据通过插值语法等方式绑定到template中;
  • 当数据变化时,template会自动进行更新来显示最新的数据;
  • 但是在某些情况下,我们希望在代码逻辑中监听某个数据的变化,这个时候就需要用侦听器watch来完成了;

将question值绑定了watch侦听,从而question的每次变换都会进行相应的逻辑处理

与v-model双向绑定的区别:

v-model只是监听了data的变化,例如键盘在input的输入时,绑定的相应data随之变化
watch监听data,并且在data改变时进行相应的逻辑处理:

例如示例代码中 this.getAnwser(newValue); 每次data改变的时候调用getAnswer方法

(例如在input中输入asdb,键盘输入了四个字符,data改变了4次,随之getAnswer方法也被调用了四次)

<div id="app"></div>

  <template id="my-app">
    <label for="question">
      请输入问题:
      <input type="text" id="question" v-model="question">
    </label>
  </template>

  <script src="../js/vue.js"></script>
  <script>
    const App = {
      template: '#my-app',
      data() {
        return {
          question: "",
          info: {
            name: "why"
          }
        }
      },
      watch: {
        question(newValue, oldValue) {
          this.getAnwser(newValue);
        }
      },
      methods: {
        getAnwser(question) {
          console.log(`${question}的问题答案是哈哈哈哈`);
        }
      }
    }

    Vue.createApp(App).mount('#app');
  </script>

${ }是es6的拼接字符串写法

侦听器watch的配置选项

我们先来看一个例子:

当点击修改info1
  • 这个时候我们使用watch来侦听info,可以侦听到吗?答案是不可以。
  • 此时改变的是info内部的属性:

info: {

        name: "kobe",

        age:"19"

}

当点击修改info2
  • 这个时候我们使用watch来侦听info,可以侦听到吗?答案是可以。
  • 此时改变的是info属性:

info: {

        name: "jack",

}

因为默认情况下,watch只是在侦听info的引用变化,对于内部属性的变化是不会做出相应的
<div id="app"></div>

  <template id="my-app">
    <button @click="btnClick1">修改info1</button>
    <button @click="btnClick2">修改info2</button>
  </template>

  <script src="../js/vue.js"></script>
  <script>
    const App = {
      template: '#my-app',
      data() {
        return {
          info: {
            name: "why",
            age:"19"
          }
        }
      },
      watch: {
        info(newValue, oldValue) {
          console.log(newValue, oldValue);
        }
      },
      methods: {
        btnClick1() {
          this.info.name = "kobe";
        },
        btnClick2() {
          this.info= {name:"jack"};
        }
      }
    }

    Vue.createApp(App).mount('#app');
  </script>

处理方法

深度监听

(注意深浅拷贝情况)

  • handle:watch中需要具体执行的方法。
  • deep:true深度检测。例如数组对象中的某个属性改变执行handle方法。

高级监听:immediate:true立即执行handle方法(首次加载、刷新、数据改变)都会执行,缺点监听不到对象属性中发生的改变

  • 这个时候无论后面数据是否有变化,侦听的函数都会有限执行一次;
watch: { 
    info: {  
        handler(newValue, oldValue) 
                {    
                  console.log(newValue, oldValue);   
                },  
        deep: true  
    			}
			}
监听对象某一个具体属性

来自vue2文档

watch:{
    'info.name': function(newValue, oldValue) {  
      console.log(newValue, oldValue);
    }
}
$watch 的API
  • 我们可以在created的生命周期中,使用 this.$watchs 来侦听;
    • 第一个参数是要侦听的源;
    • 第二个参数是侦听的回调函数callback;
    • 第三个参数是额外的其他选项,比如deep、immediate;
created() { 
    this.$watch('message', function(newValue, oldValue) {   
      console.log(newValue, oldValue); 
    },
       {
        	deep: true, 
          immediate: true
     	 }
    }

watch与computed的区别

  • 功能上:computed是计算属性,watch是监听一个值的变化,然后执行对应的回调。

  • 是否调用缓存:computed中的函数所依赖的属性没有发生变化,那么调用当前的函数的时候会从缓存中读取,而watch在每次监听的值发生变化的时候都会执行回调。

  • 是否调用return:computed中的函数必须要用return返回,watch中的函数不是必须要用return。

  • computed默认第一次加载的时候就开始监听;watch默认第一次加载不做监听,如果需要第一次加载做监听,添加immediate属性,设置为true(immediate:true)

  • computed不支持异步,当computed内有异步操作时是无法监听数据变化的,它的值会根据它所依赖的属性动态计算出来,并且计算结果会被缓存起来,只有当依赖的属性发生变化时才会重新计算。因此,computed届性必须是同步的,否则无法保证计算结果的正确性和稳定性。

  • watch支持异步操作,watch属性是用来监听效据变化的,它可以通过配置回调函效来响应效据变化,并且这个回调函数可以是异步的。Watch属性的作用是在数据发生变化时执行一些操作,它不需要返回值,因此可以使用异步操作

  • 使用场景:computed----当一个属性受多个属性影响的时候,使用computed-----购物车商品结算。watch–当一条数据影响多条数据的时候,使用watch-----搜索框.

watch:

computed:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值