浅谈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团队打造的javascript单元测试工具QUnit介绍
Feb 26 Javascript
Javascript实现动态菜单添加的实例代码
Jul 05 Javascript
JavaScript对象学习经验整理
Oct 12 Javascript
jquery自适应布局的简单实例
May 28 Javascript
Javascript vue.js表格分页,ajax异步加载数据
Oct 24 Javascript
jQuery的时间datetime控件在AngularJs中的使用实例(分享)
Aug 17 jQuery
vue如何判断dom的class
Apr 26 Javascript
使用jQuery动态设置单选框的选中效果
Dec 06 jQuery
React中this丢失的四种解决方法
Mar 12 Javascript
在layui下对元素进行事件绑定的实例
Sep 06 Javascript
Vue登录主页动态背景短视频制作
Sep 21 Javascript
vue动态设置页面title的方法实例
Aug 23 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网站基础优化方法小结
2008/09/29 PHP
js关闭当前页面(窗口)的几种方式总结
2013/03/05 Javascript
jquery 按钮状态效果 正常、移上、按下
2013/08/12 Javascript
JavaScript中this的使用详解
2013/11/08 Javascript
javascript跨浏览器的属性判断方法
2014/03/16 Javascript
js控制href内容的连接内容的变化示例
2014/04/30 Javascript
javascript学习笔记(五)原型和原型链详解
2014/10/08 Javascript
jquery中one()方法的用法实例
2015/01/16 Javascript
JavaScript使用Max函数返回两个数字中较大数的方法
2015/04/06 Javascript
jq实现左侧显示图片右侧文字滑动切换效果
2015/08/04 Javascript
JS根据key值获取URL中的参数值及把URL的参数转换成json对象
2015/08/26 Javascript
深入浅析JavaScript中的scrollTop
2016/07/11 Javascript
ajax实现加载页面、删除、查看详细信息 bootstrap美化页面!
2017/03/14 Javascript
关于bootstrap日期转化,bootstrap-editable的简单使用,bootstrap-fileinput的使用详解
2017/05/12 Javascript
基于vue2.0实现仿百度前端分页效果附实现代码
2018/10/30 Javascript
jQuery使用bind动态绑定事件无效的处理方法
2018/12/11 jQuery
webpack HappyPack实战详解
2019/10/08 Javascript
layui 数据表格 根据值(1=业务,2=机构)显示中文名称示例
2019/10/26 Javascript
[10:04]国际邀请赛采访专栏:DK.Farseer,mouz.Black^,采访员Josh专访
2013/08/05 DOTA
python的keyword模块用法实例分析
2015/06/30 Python
python3 模拟登录v2ex实例讲解
2017/07/13 Python
python版本的仿windows计划任务工具
2018/04/30 Python
Python实现对文件进行单词划分并去重排序操作示例
2018/07/10 Python
django框架基于模板 生成 excel(xls) 文件操作示例
2019/06/19 Python
一行Python代码过滤标点符号等特殊字符
2019/08/12 Python
python 类的继承 实例方法.静态方法.类方法的代码解析
2019/08/23 Python
django表单中的按钮获取数据的实例分析
2020/07/31 Python
高级销售求职信
2014/02/21 职场文书
二年级评语大全
2014/04/23 职场文书
社团活动总结范文
2014/04/26 职场文书
解除劳动关系协议书范文
2014/09/11 职场文书
八项规定整改方案
2014/10/01 职场文书
四风专项整治工作情况汇报
2014/10/28 职场文书
2014年酒店前台工作总结
2014/11/14 职场文书
新党员入党决心书
2015/09/22 职场文书
css3手动实现pc端横向滚动
2022/06/21 HTML / CSS