Vue中watch的使用

在vue中,使用watch来响应数据的变化。

一、 watch是什么?

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

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

watch的2个参数 (newValue, oldValue)

1.需要新旧对比时 可以用到第二个参数
2.参数不写,直接通过 this.数据的方式 也可以获取到最新的数据

AcNo(val, oldVal) {
                if(val != oldVal) {
                    const params = {
                        AcNo: this.AcNo
                    }
                    this.$http.post('/eweb/eweb-query.AcInfoQry.do', params).then(res => {
                        this.Balance = res.AvailBal
                        this.Currency = res.Currency
                        this.AcName = res.AcName
                    })
                }
            },

二、应用场景

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

三、应用

<1>基础用法

数据初始化

data() {
    return {
        a: 1,
        b: 'enen',
        shipStatusArr: {
            name: 'zhangsanlisi',
            age: 12
        }
    }
}

mounted

mounted () {
    this.a = 2
    this.shipStatusArr.name = 'lisi'
}

watch

(1)watch基本数据类型(string,number等)

watch: {
    a: function (newValue, oldVal) {
      console.log( newValue, oldVal )
    }

    // 也可以写成
    a(newValue, oldVal){
        console.log( newValue, oldVal )
     }
}

// handler方法和immediate属性
// 上面的例子是值变化时候,watch才执行,我们想让值最初时候watch就执行就用到了handler和immediate属性
watch: {
  a: {
    handler(newName, oldName) {
      this.fullName = newName + ' ' + this.lastName;
    },
    // 代表在wacth里声明了a这个方法之后立即先去执行handler方法,如果设置了false,那么效果和上边例子一样
    immediate: true
  }
}

(2)watch对象/数组(复杂数据类型)

# deep属性

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

watch: {
    shipStatusArr: {
      handler(newValue, oldValue) {
        console.log(newValue, oldValue)
      },
      deep: true  // 深度监听
    }
}

// 下面的做法,检测对象的时候, newVal == oldVal
 watch: {
    obj: {
      handler(newName, oldName) {
         console.log('obj.a changed');
      },
      immediate: true
    }
  } 

// 延伸
受现代 JavaScript 的限制 (以及废弃 Object.observe),Vue 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。
 默认情况下 handler 只监听obj这个属性它的引用的变化,我们只有给obj赋值的时候它才会监听到,比如我们在 mounted事件钩子函数中对obj进行重新赋值
如果此时,需要对obj对象里的属性a的值作监测,可以这样处理,这时候deep属性就派上用场了
watch: {
  obj: {
    handler(newName, oldName) {
      console.log('obj.a changed');
    },
    immediate: true,
    deep: true
  }
}
这样的方法对性能影响很大,修改obj里面任何一个属性都会触发这个监听器里的 handler。我们可以做如下处理:
watch: {
  'obj.a': {
    handler(newName, oldName) {
      console.log('obj.a changed');
    },
    immediate: true,
    // deep: true
  }
}

<2>进阶用法

(1)监听对象的某一属性

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

watch: {
    'shipStatusArr.name': function (newValue, oldVal) {
        console.log( newValue, oldVal )
    }
}

设置deep: true 则可以监听到shipStatusArr.name的变化,此时会给shipStatusArr的所有属性都加上这个监听器,当对象属性较多时,每个属性值的变化都会执行handler。如果只需要监听对象中的一个属性值,则可以做以下优化:使用字符串的形式监听对象属性。这样只会给对象的某个特定的属性加监听器。

(2)immediate属性

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

watch: {
    shipStatusArr: {
      handler(newValue, oldValue) {
        console.log(newValue, oldValue)
      },
      deep: true,
      immediate: true
    }
}

四、注意问题

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

五、工作中实际运用

情景一

有时候,在使用watch侦听数据变化后 , 需要清空某些数据 , 同时用计算属性对该字段进行判断
如果直接用等于号赋值清空 , 计算属性由于有缓存而导致 , 计算属性认为被清空的数据没有变化 , 从而不会发生重新计算
需要使用$set清空数据 , 并且让被清空的字段是响应式的

如下所示


Snipaste_2020-07-09_19-35-48.png

可以给watch检测的变量赋值

 watch: {
      Qmoney(newValue, oldValue){
           if (newValue != oldValue){
              this.Qmoney = newValue
              this.RemainingSum = parseFloat(this.detail.BillBalance) - this.Qmoney
           }
      }
  },

情景二

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

 watch: {
    search (val) {
      console.log('watch---',val)
      // if(val){  // 这里仅仅是判断val有值的情况,但不涵盖val为空,对于搜索功能,只考虑数据变化(包含数据为空的情况)执行数据获取接口即可,所以把if条件去掉即可
        this.CurrentIndex = '0'
        this.BankName = val
        this.List3 = []
        this.getData('watch')
      // }
    }
  },
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341