Vue中的 computed 与 watch

1.回顾 options.data

  • 会被Vue监听
  • 会被Vue实例代理
  • 每次对data得读写都会被Vue监控
  • Vue 会在data变化时更新视图

2.computed 计算属性

用途:

  • 模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如:
{{ message.split('').reverse().join('') }}

在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量 message 的翻转字符串。当你想要在模板中的多处包含此翻转字符串时,就会更加难以处理。

  • 因此,对于复杂得逻辑,应当使用 计算属性
  • 计算数形函数将被作为同名属性的getter 和 setter
  • 当你有一些数据需要随着其它数据变动而变动时,最好是使用计算属性
  • 计算属性默认只有 getter,不过在需要时你也可以提供一个 setter
new Vue({
  template:`
    
{{displayName}}
`, // 这里直接使用函数名 便可以得到复杂逻辑处理后的结果 methods:{ add(){ this.obj.array.push('d') console.log(this.obj.array) } }, data:{ user:{ nickName:'小欧', email:'[email protected]', phone:18888888888 } }, computed:{ displayName(){ // 计算函数 const user = this.user return user.nickName || user.phone || user.email } } }).$mount('#app')

也可以写成 get set 形式

displayName:{
    get(){
        const user = this.user
        return user.nickName || user.phone || user.email
    },
        set(value){
            this.user.nickName = value
        }
}
小例子 实现列表的筛选功能
new Vue({
    template: `
      
  • {{ u.name }} - {{ u.gender }}
`, data: { user: [ creatUser("小欧", '男'), creatUser('小巧', '女'), creatUser('小乔', '女'), creatUser('大欧', '男') ], displayUsers: [] }, computed: { displayName: {} }, created() { this.displayUsers = this.user }, methods: { showMale(){ this.displayUsers = this.user.filter(u => u.gender === '男') }, showFemale(){ this.displayUsers = this.user.filter(u => u.gender === '女') }, showAll(){ this.displayUsers = this.user } } }).$mount('#app')

使用计算属性后更加合理

let id = 0
const creatUser = (name, gender) => {
    id++
    return {
        id: id,
        name: name,
        gender: gender
    }
}
new Vue({
    template: `
      
  • {{ u.name }} - {{ u.gender }}
`, data: { user: [ creatUser("小欧", '男'), creatUser('小巧', '女'), creatUser('小乔', '女'), creatUser('大欧', '男') ], gender: '' }, computed: { displayUser() { const {user,gender} = this if(gender === ''){ return user }else if(gender === 'male'){ return this.user.filter(u => u.gender === '男') }else if(gender === 'female'){ return this.user.filter(u => u.gender === '女') } else return 0 } }, created() { this.displayUsers = this.user } }).$mount('#app')

计算属性函数在数据没有发生变化的时候不会执行函数,这就是computed 缓存

3.watch - 侦听

用途:

当需要在数据变化时执行异步或开销较大的操作时,使用watch监听是最有用的

1.实现一个撤销的例子

new Vue({
    data: {
        n: 0,
        history: [],
        inUndoMode:false
    },
    computed: {
        displayUser() {
            const {gender} = this
            if (gender === '') {
                return this.user
            } else if (gender === 'male') {
                return this.user.filter(u => u.gender === '男')
            } else if (gender === 'female') {
                return this.user.filter(u => u.gender === '女')
            } else return 0
        }
    },
    watch: {
        n(newValue,oldValue){
            if(!this.inUndoMode){
                this.history.push({from:oldValue,to:newValue})
            }
        }
    },
    template: `
      
{{ n }}


{{history}}
`, methods:{ add1(){ this.n++ }, add2(){ this.n += 2 }, minus1(){ this.n-- }, minus2(){ this.n -=2 }, undo(){ const last = this.history.pop() const old = last.from this.inUndoMode = true this.n = old this.$nextTick(() => { // 等待 watch 异步执行完毕 this.inUndoMode = false },0) } } }).$mount('#app')

2.实现一个对 computed 的模拟

new Vue({
    data: {
        user: {
            email: '[email protected]',
            nickname: '小欧',
            phone: '18888888888'
        },
        displayName: ''
    },
    computed: {},
    watch: {
        'user.email': {      //  第二层属性的写法
            handler(){
                const {user: {email, nickname, phone}} = this    // 解构赋值
                this.displayName = nickname || email || phone
            },
            immediate:true     // 第一次变化也监听
        },
        'user.phone': {
            handler(){
                const {user: {email, nickname, phone}} = this    // 解构赋值
                this.displayName = nickname || email || phone
            },
            immediate:true
        },
        'user.nickname': {
            handler(){
                const {user: {email, nickname, phone}} = this    // 解构赋值
                this.displayName = nickname || email || phone
            },
            immediate:true
        }
    },
    template: `
      
{{ displayName }}
`, methods: { changed() { console.log(arguments) const user = this.user this.displayName = user.nickname || user.phone || user.email } } }).$mount('#app')
计算属性与watch的选择:

计算属性主要着重依赖之间的变化以及缓存,而 watch 主要侧重数据变后执行函数操作,而不一定需要返回数据

4. watch的 deep 选项

watch监听数据变化,那么怎么样才算是数据变化了呢

  1. 简单数据类型的值变化,watch就认为其变化了
  2. 复杂数据类型地址变化,watch才认为其变化了

当我们希望复杂数据类型中的某个简单数据类型变化了就导致复杂类型变化就可以使用deep

watch: {
        'user.nickname': {
            handler(){
                const {user: {email, nickname, phone}} = this    // 解构赋值
                this.displayName = nickname || email || phone
            },
            deep:true    // 开启严格的监听
        }
    },

5.watch的常用写法

  1. 使用新旧值
n:function(newValue,oldValue){   // 监听n的值的变化
    ...
}
// 等同于
n(newValue,oldValue){
    ...
}
  1. 传一个函数数组
n:[fn1,fn2...]
  1. 在 method 里面定义的函数可以使用
n:'methodName'
  1. 使用处理函数以及一些选项设定
n:{
    handler:fn,
    deep:true,
    immediat:true    
}

另一种写法:

vm.$watch('xxx',fn,{deep:..,immediat:...})  //这里的'xxx'可以是一个返回字符串的函数

你可能感兴趣的:(Vue中的 computed 与 watch)