浅谈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 相关文章推荐
javascript开发中因空格引发的错误
Nov 08 Javascript
node.js中的fs.futimesSync方法使用说明
Dec 17 Javascript
js动态切换图片的方法
Jan 20 Javascript
深入浅出理解javaScript原型链
May 09 Javascript
jQuery过滤HTML标签并高亮显示关键字的方法
Aug 07 Javascript
js读取并解析JSON类型数据的方法
Nov 14 Javascript
JS限制输入框输入的实现代码
Jul 02 Javascript
vue.js中proxyTable 转发请求的实现方法
Sep 20 Javascript
angularJs自定义过滤器实现手机号信息隐藏的方法
Oct 08 Javascript
html+jQuery实现拖动滑块图片拼图验证码插件【移动端适用】
Sep 10 jQuery
javascript实现搜索筛选功能实例代码
Nov 12 Javascript
iview实现动态表单和自定义验证时间段重叠
Jan 10 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作的文本留言本的例子(六)
2006/10/09 PHP
一道关于php变量引用的面试题
2010/08/08 PHP
PHP图片验证码制作实现分享(全)
2012/05/10 PHP
微信公众平台开发之配置与请求
2015/08/26 PHP
自定义min版smarty模板引擎MinSmarty.class.php文件及用法
2016/05/20 PHP
全面解析PHP验证码的实现原理 附php验证码小案例
2016/08/17 PHP
PHP快速排序算法实现的原理及代码详解
2019/04/03 PHP
javascript div 遮罩层封锁整个页面
2009/07/10 Javascript
js页面跳转的常用方法整理
2013/10/18 Javascript
jquery判断浏览器后退时候弹出消息的方法
2014/08/11 Javascript
jquery实现页面虚拟键盘特效
2015/08/08 Javascript
JavaScript中的Function函数
2015/08/27 Javascript
jQuery autoComplete插件两种使用方式及动态改变参数值的方法详解
2016/10/24 Javascript
JavaScript实现无穷滚动加载数据
2017/05/06 Javascript
Angular使用ControlValueAccessor创建自定义表单控件
2019/03/08 Javascript
JavaScript计算正方形面积
2019/11/26 Javascript
Auto.JS实现抖音刷宝等刷视频app,自动点赞,自动滑屏,自动切换视频功能
2020/05/08 Javascript
Vue3.0的优化总结
2020/10/16 Javascript
jQuery-App输入框实现实时搜索
2020/11/19 jQuery
使用Python制作微信跳一跳辅助
2018/01/31 Python
基于python实现聊天室程序
2018/07/27 Python
详解将Django部署到Centos7全攻略
2018/09/26 Python
pyCharm 设置调试输出窗口中文显示方式(字符码转换)
2020/06/09 Python
解决Python安装cryptography报错问题
2020/09/03 Python
Python+OpenCV图像处理——实现直线检测
2020/10/23 Python
Boda Skins皮衣官网:奢侈皮夹克,全球配送
2016/12/15 全球购物
SmartBuyGlasses意大利:购买太阳镜、眼镜和隐形眼镜
2018/11/20 全球购物
优秀学生事迹材料
2014/02/08 职场文书
园艺师求职信
2014/03/10 职场文书
社区爱国卫生月活动总结
2014/06/30 职场文书
2015年六一儿童节活动总结
2015/02/11 职场文书
员工开除通知书
2015/04/25 职场文书
冰雪公主观后感
2015/06/16 职场文书
家庭经济困难证明
2015/06/23 职场文书
积极心理学课程心得体会
2016/01/22 职场文书
Spring中bean的生命周期之getSingleton方法
2021/06/30 Java/Android