浅谈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 相关文章推荐
Jquery实现三层遍历删除功能代码
Apr 23 Javascript
js 鼠标移动显示图片的简单实例
Dec 25 Javascript
js模糊查询实例分享
Dec 26 Javascript
javascript 删除数组元素和清空数组的简单方法
Feb 24 Javascript
VUE中使用Vue-resource完成交互
Jul 21 Javascript
详解在vue-cli中使用路由
Sep 25 Javascript
jquery 通过ajax请求获取后台数据显示在表格上的方法
Aug 08 jQuery
Vue对象赋值视图不更新问题及解决方法
Jun 03 Javascript
jQuery实现滑动星星评分效果(每日分享)
Nov 13 jQuery
JavaScript进阶(三)闭包原理与用法详解
May 09 Javascript
Vue.js 带下拉选项的输入框(Textbox with Dropdown)组件
Apr 17 Vue.js
Vue提供的三种调试方式你知道吗
Jan 18 Vue.js
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运行出现Call to undefined function curl_init()的解决方法
2010/11/02 PHP
如何使用php判断服务器是否是HTTPS连接
2013/07/05 PHP
解决php接收shell返回的结果中文乱码问题
2014/01/23 PHP
Yii实现多数据库主从读写分离的方法
2014/12/29 PHP
php实现的SSO单点登录系统接入功能示例分析
2016/10/12 PHP
PHP-FPM运行状态的实时查看及监控详解
2016/11/18 PHP
php批量删除操作代码分享
2017/02/26 PHP
thinkPHP数据查询常用方法总结【select,find,getField,query】
2017/03/15 PHP
ThinkPHP3.2.3框架实现的空模块、空控制器、空操作,跳转到错误404页面图文详解
2019/04/03 PHP
JS中style属性
2006/10/11 Javascript
javascript 动态加载 css 方法总结
2009/07/11 Javascript
js indexOf()定义和用法
2012/10/21 Javascript
jQuery实现在下拉列表选择时获取json数据的方法
2015/04/16 Javascript
jQuery实现带玻璃流光质感的手风琴特效
2015/11/20 Javascript
详解Angularjs中的依赖注入
2016/03/11 Javascript
解决OneThink中无法异步提交kindeditor文本框中修改后的内容方法
2017/05/05 Javascript
EasyUI Tree树组件无限循环的解决方法
2017/09/27 Javascript
使用RxJS更优雅地进行定时请求详析
2019/06/02 Javascript
JavaScript动态检测密码强度原理及实现方法详解
2019/06/11 Javascript
[01:04:02]DOTA2-DPC中国联赛 正赛 Elephant vs IG BO3 第二场 1月24日
2021/03/11 DOTA
Python使用wxPython实现计算器
2018/01/30 Python
解决pandas 作图无法显示中文的问题
2018/05/24 Python
基于python代码实现简易滤除数字的方法
2018/07/17 Python
Python global全局变量函数详解
2018/09/18 Python
Python将string转换到float的实例方法
2019/07/29 Python
python 实现矩阵填充0的例子
2019/11/29 Python
app内嵌H5 webview 本地缓存问题的解决
2020/10/19 HTML / CSS
艺术用品:Arteza
2018/11/25 全球购物
GUESS Factory加拿大:牛仔裤、服装及配饰
2019/09/20 全球购物
海蓝之谜英国官网:La Mer英国
2020/01/15 全球购物
分布式数据库需要考虑哪些问题
2013/12/08 面试题
优秀毕业自我鉴定
2014/02/15 职场文书
优秀的2014年两会精神解读
2014/03/17 职场文书
会计专业应届生自荐信
2014/06/28 职场文书
python中pandas对多列进行分组统计的实现
2021/06/18 Python