vue中watch详解

1,397 阅读2分钟

Watch概述

一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性。

简单地监听

<body>
    <div id="app">
        <input type="text" v-model="num">
    </div>
    <script src="vue.js"></script>
    <script>
        new Vue({
            el: '#app',
            data: {
                num: ''
            },
            watch: {
                num(newVal, oldVal) {
                // 监听 num 属性的数据变化
                // 作用 : 只要 num 的值发生变化,这个方法就会被调用
                // 第一个参数 : 新值
                // 第二个参数 : 旧值,之前的值
                    console.log('oldVal:',oldVal)
                    console.log('newVal:',newVal)
                }
            }
        })
    </script>
    </body>

immediate(立即处理 进入页面就触发)

<body>
<div id="app">
    <input type="text" v-model="num">
</div>
<script src="vue.js"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            num: 1
        },
        watch: {
            num: {
            	// 数据发生变化就会调用这个函数  
                handler(newVal, oldVal) {
                    console.log('oldVal:', oldVal)
                    console.log('newVal:', newVal)
                },
                // 立即处理 进入页面就触发
                immediate: true
            }
        }
    })
</script>
</body>

deep(深度监听)

    对象和数组都是引用类型,引用类型变量存的是地址,地址没有变,所以不会触发watch。这时我们需要进行深度监听,就需要加上一个属性 deep,值为 true

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./vue.js"></script>
</head>
<body>
      <div id="app">
         <input type="button" value="更改名字" @click="change">
        <p>{{food.name}}</p> 
      </div>
      <script>
          new Vue({
              el: "#app",
              data: {
                  food: {
                      id: 1,
                      name: '苹果'
                  }
              },
              methods: {
                change(){
                    this.food.name = "西瓜"
                }
              },
              watch: {
                  // 第一种方式:监听整个对象,每个属性值的变化都会执行handler
        	      // 注意:属性值发生变化后,handler执行后获取的 newVal 值和 oldVal 值是一样的
                  food :{
                      handler(newVal,oldVal){
                        console.log('oldVal:', oldVal)
                        console.log('newVal:', newVal)
                      },
                       // 立即处理 进入页面就触发
                        immediate: true,
                        // 深度监听 属性的变化
                        deep: true
                  },
                   // 第二种方式:监听对象的某个属性,被监听的属性值发生变化就会执行函数
                    // 函数执行后,获取的 newVal 值和 oldVal 值不一样
                    'food.name'(newVal, oldVal) {
                        console.log('oldVal:', oldVal)   // 苹果
                        console.log('newVal:', newVal)   // 西瓜
                    }

              }
              
          })
          /* 
          watch  监听属性变化
          */
      </script>
</body>
</html>

Watch和computed的区别

计算属性computed :
  1. 支持缓存,只有依赖数据发生改变,才会重新进行计算
  2. 不支持异步,当computed内有异步操作时无效,无法监听数据的变化
  3. computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值
  4. 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed
  5. 如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。
watch
  1. 不支持缓存,数据变,直接会触发相应的操作;
  2. watch支持异步;
  3. 监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
  4. 当一个属性发生变化时,需要执行对应的操作;一对多;
  5. 监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数:   
  6. immediate:组件加载立即触发回调函数执行,   
  7. deep: 深度监听,为了发现对象内部值的变化,复杂类型的数据时使用,例如数组中的对象内容的改变,注意监听数组的变动不需要这么做。注意:deep无法监听到数组的变动和对象的新增,参考vue数组变异,只有以响应式的方式触发才会被监听到。