浅谈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 相关文章推荐
Prototype最新版(1.5 rc2)使用指南(1)
Jan 10 Javascript
DIV外区域Click后关闭DIV的实现代码
Dec 21 Javascript
分享8款优秀的 jQuery 加载动画和进度条插件
Oct 24 Javascript
jquery怎样实现ajax联动框(一)
Mar 08 Javascript
js简单抽奖代码
Jan 16 Javascript
JQuery中解决重复动画的方法
Oct 17 Javascript
微信小程序 页面跳转传递值几种方法详解
Jan 12 Javascript
js中document.referrer实现移动端返回上一页
Feb 22 Javascript
jquery实现手机端单店铺购物车结算删除功能
Feb 22 Javascript
微信小程序用户授权、位置授权及获取微信绑定手机号
Jul 18 Javascript
在Vue中使用Echarts可视化库的完整步骤记录
Nov 18 Vue.js
js面向对象方式实现拖拽效果
Mar 03 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将csv文件导入到mysql数据库的方法
2014/12/24 PHP
讲解WordPress中用于获取评论模板和搜索表单的PHP函数
2015/12/28 PHP
ThinkPHP5 验证器的具体使用
2018/05/31 PHP
PHP的PDO事务与自动提交
2019/01/24 PHP
Javascript Cookie读写删除操作的函数
2010/03/02 Javascript
laytpl 精致巧妙的JavaScript模板引擎
2014/08/29 Javascript
js+html5生成自动排列对话框实例
2017/10/09 Javascript
vue组件生命周期详解
2017/11/07 Javascript
element-ui 中的table的列隐藏问题解决
2018/08/24 Javascript
vue-quill-editor富文本编辑器简单使用方法
2018/09/21 Javascript
vue使用laydate时间插件的方法
2018/11/14 Javascript
jquery插件开发模式实例详解
2019/07/20 jQuery
JavaScript This指向问题详解
2019/11/25 Javascript
微信小程序吸底区域适配iPhoneX的实现
2020/04/09 Javascript
vue中全局路由守卫中替代this操作(this.$store/this.$vux)
2020/07/24 Javascript
Openlayers实现扩散的动态点(水纹效果)
2020/08/17 Javascript
使用Typescript开发微信小程序的步骤详解
2021/01/12 Javascript
[03:49]辉夜杯现场龙骑士COSER秀情商“我喜欢芬队!”
2015/12/27 DOTA
Python中random模块生成随机数详解
2016/03/10 Python
python版opencv摄像头人脸实时检测方法
2018/08/03 Python
Python调用C++,通过Pybind11制作Python接口
2018/10/16 Python
set在python里的含义和用法
2019/06/24 Python
python 实现批量替换文本中的某部分内容
2019/12/13 Python
详解java调用python的几种用法(看这篇就够了)
2020/12/10 Python
python爬虫scrapy基于CrawlSpider类的全站数据爬取示例解析
2021/02/20 Python
Html5 postMessage实现跨域消息传递
2016/03/11 HTML / CSS
日本运动品牌美津浓官方购物网站:MIZUNO SHOP
2016/08/21 全球购物
行政工作个人的自我评价
2014/02/13 职场文书
一岗双责责任书
2014/04/15 职场文书
陈安之励志演讲稿
2014/08/21 职场文书
医德医魂心得体会
2014/09/11 职场文书
群众路线领导班子整改方案
2014/10/25 职场文书
教务处教学工作总结
2015/08/10 职场文书
如何用JavaScript实现一个数组惰性求值库
2021/05/05 Javascript
36个正则表达式(开发效率提高80%)
2021/11/17 Javascript
CSS实现背景图片全屏铺满自适应的3种方式
2022/07/07 HTML / CSS