美文网首页
聊聊vue的计算属性computed与侦听器watch

聊聊vue的计算属性computed与侦听器watch

作者: CalvinXie | 来源:发表于2019-10-01 19:36 被阅读0次

    聊聊vue的计算属性和帧听器

    th (1).jpg

    vue的计算属性computed和侦听器watch都是监听数据变化。

    computed

    顾名思义,computed 中文为计算;所以其在vue单文件组件中做的就是对数据进行简单的一些逻辑计算,这在项目开发中很方便我们队原始数据处理。** 重要的是计算属性基于它们的响应式依赖进行缓存的。**只有当响应依赖关系变了即值发生变化了才会重新计算。否则,直接利用缓存,这样既避免多次调用函数又提升性能。

    const vm = new Vue({
      el: '#demo',
      data: {
       firstName: 'kevin',
       lastName: 'Xie'
      },
      computed: {
       fullName () {
         return this.firstName + ' ' + this.lastName
       }
      }   
    })
    
    

    computed 有两个属性getter 和 setter,上面我们只用到了getter属性,默认是getter属性,如果需要主动去改变getter的值,可以通过setter来实现。

    // ...
    computed: {
      fullName: {
        // getter
        get: function () {
          return this.firstName + ' ' + this.lastName
        },
        // setter
        set: function (newValue) {
          var names = newValue.split(' ')
          this.firstName = names[0]
          this.lastName = names[names.length - 1]
        }
      }
    }
    // ...
    

    watch

    watch 则多数监听数据改变去执行异步操作和逻辑复杂的操作。同样watch也是在当值发生改变才会触发,不过没有缓存机制。

    const vm = new Vue({
      el: '#demo2',
      data: {
        visible: false
      },
      watch: {
        visible (newVal, oldVal) {
            // ...some code
        }
      }
    })
    
    

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

    var vm = new Vue({
      data: {
        a: 1,
        b: 2,
        c: 3,
        d: 4,
        e: {
          f: {
            g: 5
          }
        }
      },
      watch: {
        a: function (val, oldVal) {
          console.log('new: %s, old: %s', val, oldVal)
        },
        // 方法名
        b: 'someMethod',
        // 该回调会在任何被侦听的对象的 property 改变时被调用,不论其被嵌套多深
        c: {
          handler: function (val, oldVal) { /* ... */ },
          deep: true
        },
        // 该回调将会在侦听开始之后被立即调用
        d: {
          handler: 'someMethod',
          immediate: true
        },
        e: [
          'handle1',
          function handle2 (val, oldVal) { /* ... */ },
          {
            handler: function handle3 (val, oldVal) { /* ... */ },
            /* ... */
          }
        ],
        // watch vm.e.f's value: {g: 5}
        'e.f': function (val, oldVal) { /* ... */ }
      }
    })
    vm.a = 2 // => new: 2, old: 1
    
    
    Vue.js-cover.png

    ** 注意,不应该使用箭头函数来定义 watcher 函数 (例如 searchQuery: newValue => this.updateAutocomplete(newValue))。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.updateAutocomplete 将是 undefined**
    有时候computed可以和watch配合使用,比如你要同时监听两个值得变化。可以这样写:

    const vm = new Vue({
      el: '#demo3',
      data: {
        value1: '',
        value2: ''
      },
      computed: {
        doubleVal () {
          return {
            val1: this.value1,
            val2: this.value2
          }
        }    
      },
      watch: {
        doubleVal(v) {
         console.log(v) // 这里的v就包括两个值
        }
      }
    })
    
    

    还有一点在开发可能会遇到,就是watch一个对象时,只有当给对象赋值了才触发watch,但我们需求是要在初始化对象时就触发,这个时候deep属性就派上用场了。

    const vm = new Vue({
      el: '#demo4',
      data: {
        obj: {
          a: 1,
          b: 'test'
        }
      },
      watch: {
        obj: {
          handler(v) {
           console.log(v) // 不会执行
          }
        }
      }
    })
    const vm = new Vue({
      el: '#demo5',
      data: {
        obj: {
          a: 1,
          b: 'test'
        }
      },
      watch: {
        obj: {
          handler(v) {
           console.log(v) // {a: 1, b: 'test'}
          },
          deep: true
        }
      }
    })
    

    但是这样会影响性能,使得对象某一个属性发生改变时vue就啊哟深度遍历整个对象,对每个属性都会触发handler函数,建议采用字符串形式监听

    const vm = new Vue({
      el: '#demo6',
      data: {
        obj: {
          a: 1,
          b: ''
        }
      },
      watch: {
        'obj.a': {
          handler(v) {
           console.log(v) // 1
          }
        }
      }
    })
    

    还有一个场景是当某个值初始化但watch没有监听到,然而我们同样需要立即监听,则immediate属性派上用场了。

    const vm = new Vue({
      el: '#demo7',
      data: {
        say: 'hello world'
      },
      watch: {
        say: {
          handler(v) {
           console.log(v) // 不会执行
          }
        }
      }
    })
    
    const vm = new Vue({
      el: '#demo8',
      data: {
        say: 'hello world'
      },
      watch: {
        say: {
          handler(v) {
           console.log(v) // hello world
          },
          immediate: true
        }
      }
    })
    

    watch在不用的时候需要注销它,在单文件组件销毁时vue会帮我们自动注销,但如果我们没在单文件组件使用,app.$watch调用后会返回一个值,就是unWatch方法,你要注销 watch 只要调用unWatch方法就可以了。

    const unWatch = app.$watch('text', (newVal, oldVal) => {
      console.log(`${newVal} : ${oldVal}`)
    })
    
    unWatch() // 手动注销watch
    

    好了,今天vue的计算属性和帧听器就聊到这了, 欢迎大家批评指正。


    7c9f3d7e721357d22c3d0b1489ef25aa7d5f08b28aa4-aZGibK_fw658.jpg

    相关文章

      网友评论

          本文标题:聊聊vue的计算属性computed与侦听器watch

          本文链接:https://www.haomeiwen.com/subject/msakpctx.html