Vue中watch的使用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue中watch的使用相关的知识,希望对你有一定的参考价值。

参考技术A 在vue中,使用watch来响应数据的变化。

监测 Vue 实例变化的一个表达式或方法。回调函数得到的参数为新值和旧值,用一个函数取代。
简洁的说:watch的作用可以监控一个值的变换,并调用因为变化需要执行的方法。可以通过watch动态改变关联的状态。

watch函数的参数中,第一个是改变之前的值,第二个是改变之后的值, 这两个参数非常有用。

watch的2个参数 (newValue, oldValue)

当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。例如ajax请求,复杂的业务逻辑处理等。

数据初始化

mounted

watch

需要使用handler函数,并且开启深度侦听deep
当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听。
当监测为对象的时候(非数组情况),deep = true 可以监测对象中属性的变化,并且(监测为对象的时候,newVal == oldVal)
此时,需要watch对象的某一具体属性才可以监听到数据的变化,具体做法是使用对象点方法获取到属性,并且用引号
(1)如果要观察data下一个对象的属性,可以使用 '对象.属性' 的方式, 注意: 一定要要引号。
(2)如果改变了一个对象的属性,就必须使用 deep: true, 否则检测不到变化。
(3)数组(一维、多维)的变化不需要通过深度监听,对象数组中对象的属性变化则需要deep深度监听。

以上监听shipStatusArr的用法,会在shipStatusArr中任一属性变化时触发,如果是只监听shipStatusArr的name变化,更优写法是:

进入组件的时候,第一次并不会执行watch,只有值发生改变才会执行 , 是因为immediate 默认 false
当 immediate = true 的时候,进入组件会立即执行。并且可以监测到组件传递数据。
回调将会在侦听开始之后被立即调用。
如果我们需要在最初绑定值的时候也执行函数,则就需要用到immediate属性。
监听的复杂数据后面写成对象形式,包含handler方法和immediate,之前我们写的函数其实就是在写这个handler方法。
immediate表示在watch中首次绑定的时候,是否执行handler,值为true则表示在watch中声明的时候,就立即执行handler方法,值为false,则和一般使用watch一样,在数据发生变化的时候才执行handler。

(1)在watch中不要使用箭头函数,即不应该使用箭头函数来定义 watcher 函数 , 因为箭头函数中的this是指向当前作用域
(2)开启深度侦听后,触发一次,两个数据一致,这是vue做了处理
=>复杂数据类型的侦听需要开启深度侦听才可以检测到内部数据的改变,但开启深度侦听后,2个参数值是相同的,都是为数据的内存地址,精确到对象的属性名进行深度侦听可以解决此问题
=>如果修改复杂类型内部的数据也会触发,触发的频率就回比较高,因为复制类型数据可能多个地方使用,如果都会触发侦听器,则会一直执行,因此vue做了这个优化,不发生触发,如果非要侦听,可以使用深度侦听

如下所示

watch监听的值可以不判断条件,只要数据发生变化就执行某些逻辑
比如 搜索功能实现

vue中watch的使用

vue中watch的使用

  vue中的watch是一个比较重要的概念,通过他我们可以检测data的变化,下面进行详细的介绍。

  watch定义方式如下:

{[key: string]: string | Function | Object  }

  即在watch中,

  • 键是一个字符串,它是被观测的对象。
  • 值可以是一个字符串,这个字符串是方法名。
  • 值还可以是一个函数,但不能使用箭头函数的形式,this会出现问题。
  • 值也可以是一个对象,其中包含回调函数可以其他一些选项:比如是否深度遍历。

  举例如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>vue</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script>
</head>
<body>
    <script>
      var vm = new Vue({
        data: {
          a: 1,
          b: 2,
          c: {
            name: "JohnZhu"
          }
        },
        watch: {
          a: function (val, oldVal) {
            console.log(\'new a: %s, old a: %s\', val, oldVal)
          },
          // 方法名
          b: \'someMethod\',

          // 深度 watcher, 检测到变化,并打印出c.name变化前后的结果
          // \'c.name\': {
          //   handler: function (val, oldVal) { 
          //     console.log(\'new c: %s, old c: %s\', val, oldVal);
          //   },
          //   deep: true
          // },

          // 报错 必须用c.name,否则在data下不能直接找到name
          // name: function () {
          //   console.log(\'new c: %s, old c: %s\', val, oldVal);
          // }

          // 报错,键值必须是一个字符串,所以用引号括起来
          // c.name: {
          //   handler: function (val, oldVal) {
          //     console.log(\'new c: %s, old c: %s\', val, oldVal);
          //   },
          //   deep: true
          // }

          // 这里未检测到变化
          // c : {
          //   handler: function (val, oldVal) { 
          //     console.log(\'new c: %s, old c: %s\', val, oldVal);
          //   },
          //   deep: false
          // },
         
          // 成功检测到变化 
          // c : {
          //   handler: function (val, oldVal) { 
          //     console.log(\'new c: %s, old c: %s\', val, oldVal);
          //   },
          //   deep: true
          // },

          // 检测不到变化,因为参数 deep 的默认值是false
          // c : {
          //   handler: function (val, oldVal) { 
          //     console.log(\'new c: %s, old c: %s\', val, oldVal);
          //   },
          // },
        },
        methods: {
          someMethod: function () {
            alert("b is changed");
          }
        }
      })
      vm.a = 2; // new: 2, old: 1
      vm.b = 666; // alert 666
      vm.c.name = "HTT";
    </script>
</body>
</html>

 

函数执行之后,分别在控制台中打印出new: 2, old:1 以及 alert 666。 

  • 可以看出, watch函数的参数中,第一个是改变之前的值,第二个是改变之后的值, 这两个参数非常有用。
  • 这里分别使用了 三种定义函数(或option)的方法。
  • 如果要观察data下一个对象的属性,我们可以使用 \'对象.属性\' 的方式, 注意: 一定要要引号。
  • 如果改变了一个对象的属性,就必须使用 deep: true, 否则检测不到变化。 

 

举例:

 

这样的一个组件,当我想要同级输入的字数并希望在字数达到一定的数目时,给出提示,就可以watch字数, 即v-model实现,当字数的length改变时,我们判断, 然后给出相应的提示:

最后贴出完整的代码:

<template>
  <div class="add-remark">
    <div class="input">
      <textarea maxlength="50" placeholder="请输入备注,最多50个字哦" v-model="message"></textarea>
      <span class="font-number" >{{message.length}}/50</span>
    </div>
    <div class="hint-content" v-on:click="handleHint($event)">
      <span class="hint">不吃辣</span>
      <span class="hint">少放辣</span>
      <span class="hint">多放辣</span>
      <span class="hint">不吃蒜</span>
      <span class="hint">不吃香菜</span>
      <span class="hint">不吃葱</span>
    </div>
    <div class="btn" v-on:click="goback">完成</div>
  </div>
</template>

<style scoped lang="less">
  @main-color: #51B1B0;
  @sub-color: #eeefef;
  div.add-remark {
    div.input {
      position: relative;
      padding: 0.2rem 0.5rem;
      textarea {
        box-sizing: border-box;
        width: 100%;
        height: 4rem;
        font-size: 0.4rem;
        padding: 0.3rem;
        border: 0.0294rem solid @sub-color;
        &:focus {
          box-shadow: 0 0 0.0417rem @main-color;
        }
      }
      span.font-number {
        position: absolute;
        font-size: 0.4rem;
        color: #aaa;
        bottom: 0.5rem;
        right: 0.7rem;
      }
    }
    div.hint-content {
      padding: 0.2rem;
      span.hint {
        display: inline-block;
        margin: 0.2rem 0.3rem 0.2rem 0.3rem;
        padding: 0.25rem;
        border: 0.02rem solid @sub-color;
        border-radius: 0.1rem;
        &:active {
          background-color: @sub-color;
        }
      }
    }
    div.btn {
      width: 9rem;
      height: 1rem;
      margin: 0.3rem auto;
      line-height: 1rem;
      text-align: center;
      background-color: @main-color;
      font-size: 0.45rem;
      font-weight: bold;
      color: white;
      border-radius: 0.2rem;
    }
  }
</style>

<script>
  export default {
    data () {
      return {
        message: ""
      }
    },
    watch: {
      message: function (val, oldValue) {
        if (val.length == 50) {
          this.$toast("备注最多输入50字哦");
        }
      }
    },
    methods: {
      handleHint: function (e) {
        if (e.target.nodeName.toLowerCase() == "span") {
          this.message += ("  " + e.target.innerHTML )
        }
      },
      goback () {
        this.$router.back();
      }
    }
  }
</script>
View Code

 

 

 

 

 

 

https://cn.vuejs.org/v2/api/#watch

http://www.jianshu.com/p/ffe50c5e3368

http://www.cnblogs.com/dupd/p/5887907.html

https://cn.vuejs.org/v2/guide/computed.html#Computed-属性-vs-Watched-属性、

 

 

 

 

仰天大笑出门去,我辈岂是蓬蒿人。

以上是关于Vue中watch的使用的主要内容,如果未能解决你的问题,请参考以下文章

Vue中watch的使用

vue watch原理

vue watch中deep和immediate的用法

如何使用vue.js中的$watch

vue的watch中可以使用Promise吗

vue中$watch源码阅读笔记