浅谈vue.watch的触发条件是什么


Posted in Javascript onNovember 07, 2020

很多人习惯用watch,但是却很少有人知道watch的真正触发条件。如果不是对vue原理了如指掌,请谨慎使用watch。

示例1,下面会触发watch 吗?

<script>
 new Vue({
 data() {
  return {
  city: {id: 1, name: 'Beijing'}
  }
 },
 watch: {
  city() {
  console.log('city changed')
  }
 },
 created() {
  this.city = {id: 1, name: 'Beijing'}
 }
 })
</script>

会触发,因为在created方法里面重新给city赋值了一个对象,city前后的指向不同了

示例2:

<script>
 new Vue({
 data() {
  return {
  city: {id: 1, name: 'Beijing'}
  }
 },
 watch: {
  city() {
  console.log('city changed')
  }
 },
 created() {
  this.city.name = 'Shanghai'
 }
 })
</script>

不会触发, 因为created方法执行之后, city的指向没有变

如果我们期望捕获这种更新,应该这样写代码:

watch: {
 city: {
  handler: () => console.log('city changed'),
  deep: true
 }
}

将选项deep设为true能让vue捕获对象内部的变化。

下面讨论一下watch一个数组:

<script>
new Vue({
 el: '#body',
 data() {
  return {
   cities: ['Beijing', 'Tianjin']
  }
 },
 watch: {
  cities() {
   console.log('cities changed')
  }
 }
})
</script>

那下面哪些操作会触发cities的watch回调呢?

this.cities = ['Beijing', 'Tianjin']
this.cities.push('Xiamen')
this.cities = this.cities.slice(0, 1)
this.cities.pop();
this.cities.sort((a,b)=>a.localeCompare(b));
this.cities[0] = 'Shenzhen'
this.cities.splice(0, 1)
this.cities.length = 0

答案是只有最后三行不会触发。

补充知识:vue 深度watch与watch立即触发回调

基础用法

搜索框输入搜索关键字的时候,可以自动触发搜索,此时除了监听搜索框的change事件之外,我们也可以通过watch监听搜索关键字的变化。

<template>
 <div>
  <span>搜索</span>
  <input v-model="searchVal" />
 </div>
</template>
<script>
export default {
 data() {
 return {
  searchVal: ''
 }
 },
 watch: {
 // 在值发生变化之后,重新加载数据
 searchVal(newValue, oldValue) {
  if (newValue !== oldValue) {
  this.loadData()
  }
 }
 },
 methods: {
 loadData() {
  // 重新加载数据,此处需要通过函数防抖
 }
 }
}
</script>

立即触发

通过上面的代码,现在已经可以在值发生变化的时候触发加载数据了,但是如果要在页面初始化时候加载数据,我们还需要在created或者mounted生命周期钩子里面再次调用loadData方法。不过,现在可以不用这样写了,通过配置watch的立即触发属性,就可以满足了。

export default {
 watch: {
 // 在值发生变化之后,重新加载数据
 searchValue: {
 // 通过handler来监听属性变化, 初次调用 newValue为""空字符串, oldValue为 undefined
  handler(newValue, oldValue) {
  if (newValue !== oldValue) {
   this.loadData()
  }
  },
  // 配置立即执行属性
  immediate: true
 }
 }
}

深度监听

一个表单页面,需求希望用户在修改表单的任意一项之后,表单页面就需要变更为被修改状态。如果按照上例中watch的写法,那么我们就需要去监听表单每一个属性,太麻烦了,这时候就需要用到watch的深度监听deep

export default {
 data() {
 return {
  formData: {
  name: '',
  sex: '',
  age: 0,
  deptId: ''
  }
 }
 },
 watch: {
 // 在值发生变化之后,重新加载数据
 formData: {
  // 需要注意,因为对象引用的原因, newValue和oldValue的值一直相等
  handler(newValue, oldValue) {
  // 在这里标记页面编辑状态
  },
  // 通过指定deep属性为true, watch会监听对象里面每一个值的变化
  deep: true
 }
 }
}

随时监听,随时取消,了解一下$watch

有这样一个需求,有一个表单,在编辑的时候需要监听表单的变化,如果发生变化则保存按钮启用,否则保存按钮禁用。

这时候对于新增表单来说,可以直接通过watch去监听表单数据(假设是formData),如上例所述,但对于编辑表单来说,表单需要回填数据,这时候会修改formData的值,会触发watch,无法准确的判断是否启用保存按钮。现在你就需要了解一下$watch

export default {
 data() {
 return {
  formData: {
  name: '',
  age: 0
  }
 }
 },
 created() {
 this.$_loadData()
 },
 methods: {
 // 模拟异步请求数据
 $_loadData() {
  setTimeout(() => {
  // 先赋值
  this.formData = {
   name: '子君',
   age: 18
  }
  // 等表单数据回填之后,监听数据是否发生变化
  const unwatch = this.$watch(
   'formData',
   () => {
   console.log('数据发生了变化')
   },
   {
   deep: true
   }
  )
  // 模拟数据发生了变化
  setTimeout(() => {
   this.formData.name = '张三'
  }, 1000)
  }, 1000)
 }
 }
}

根据上例可以看到,我们可以在需要的时候通过this.$watch来监听数据变化。那么如何取消监听呢,上例中this.$watch返回了一个值unwatch,是一个函数,在需要取消的时候,执行 unwatch()即可取消

以上这篇浅谈vue.watch的触发条件是什么就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
html下载本地
Jun 19 Javascript
jquery中获取select选中值的代码
Jun 27 Javascript
关于二级域名下使用一级域名下的COOKIE的问题
Nov 07 Javascript
jBox 2.3基于jquery的最新多功能对话框插件 常见使用问题解答
Nov 10 Javascript
用javascript判断IE版本号简单实用且向后兼容
Sep 11 Javascript
Flow之一个新的Javascript静态类型检查器
Dec 21 Javascript
Vue.js实现表格动态增加删除的方法(附源码下载)
Jan 20 Javascript
jquery一键控制checkbox全选、反选或全不选
Oct 16 jQuery
Angular封装搜索框组件操作示例
Apr 25 Javascript
微信小程序实现吸顶特效
Jan 08 Javascript
JavaScript实现PC端横向轮播图
Feb 07 Javascript
基于vue的tab-list类目切换商品列表组件的示例代码
Feb 14 Javascript
html+vue.js 实现漂亮分页功能可兼容IE
Nov 07 #Javascript
解决vue watch数据的方法被调用了两次的问题
Nov 07 #Javascript
vue 避免变量赋值后双向绑定的操作
Nov 07 #Javascript
浅谈Vue static 静态资源路径 和 style问题
Nov 07 #Javascript
解决VueCil代理本地proxytable无效报错404的问题
Nov 07 #Javascript
Nuxt 项目性能优化调研分析
Nov 07 #Javascript
js实现日历
Nov 07 #Javascript
You might like
php循环语句 for()与foreach()用法区别介绍
2012/09/05 PHP
微信公众平台开发教程②微信端分享功能图文详解
2019/04/10 PHP
My Desktop :) 桌面式代码
2008/12/29 Javascript
js判断字符是否是汉字的两种方法小结
2014/01/03 Javascript
下拉框select的绑定示例
2014/09/04 Javascript
jquery获取radio值(单选组radio)
2014/10/16 Javascript
以jQuery中$.Deferred对象为例讲解promise对象是如何处理异步问题
2015/11/13 Javascript
javascript下使用Promise封装FileReader
2016/02/19 Javascript
jQuery技巧之让任何组件都支持类似DOM的事件管理
2016/04/05 Javascript
详解Angular 4.x NgIf 的用法
2017/05/22 Javascript
Vue Ajax跨域请求实例详解
2017/06/20 Javascript
微信小程序中使用Async-await方法异步请求变为同步请求方法
2019/03/28 Javascript
Angular8路由守卫原理和使用方法
2019/08/29 Javascript
[02:19]DOTA2女子战队FOX视频专访:希望更多美眉一起加入
2013/10/15 DOTA
[41:21]夜魇凡尔赛茶话会 第三期02:看图识人
2021/03/11 DOTA
Python开发如何在ubuntu 15.10 上配置vim
2016/01/25 Python
windows 10下安装搭建django1.10.3和Apache2.4的方法
2017/04/05 Python
关于python2 csv写入空白行的问题
2018/06/22 Python
Python装饰器使用你可能不知道的几种姿势
2019/10/25 Python
python实现四人制扑克牌游戏
2020/04/22 Python
美国标志性加大尺码时装品牌:Ashley Stewart
2016/12/15 全球购物
澳大利亚汽车零部件、音响及配件超市:Automotive Superstore
2018/06/19 全球购物
Ruby如何实现动态方法调用
2012/11/18 面试题
DELPHI面试题研发笔试试卷
2015/11/08 面试题
销售行业个人求职自荐信
2013/09/25 职场文书
大学生职业生涯规划方案
2014/01/03 职场文书
护理专业大学生自我推荐信
2014/01/25 职场文书
善意的谎言事例
2014/02/15 职场文书
规划编制实施方案
2014/03/15 职场文书
共产党员承诺书
2014/03/25 职场文书
小学开学标语
2014/07/01 职场文书
领导干部群众路线对照检查材料
2014/11/05 职场文书
岳麓书院导游词
2015/02/03 职场文书
遗失说明具结保证书
2015/02/26 职场文书
十大最帅动漫男主 碓冰拓海上榜,第一是《灌篮高手》男主角
2022/03/18 日漫
【海涛dota】偶遇拉娜娅 质量局德鲁伊第一视角解说
2022/04/01 DOTA