Vue中this.$nextTick的作用及用法


Posted in Javascript onFebruary 04, 2020

Vue实现响应式后DOM的变化

data对象中数据改变是如何追踪的?

vue将遍历data对象中所有的属性,并通过 Object.defineProperty 把这些属性全部转为 getter/setter;但是我们是没有办法看到 getter/setter的,但是在内部它们让 Vue 能够追踪依赖,在属性被访问和修改时通知变更。

每个组件都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据属性记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

Vue是无法检测到data对象属性的添加和删除

原因:Vue在对初始化组件时会对对象属性执行getter/setter转化,所以属性必须在data对象上存在才能让Vue将它转化为初始化。

var vm = new Vue({
 data:{
 a:1
 }
 })

 // `vm.a` 是响应式的

 vm.b = 2
 // `vm.b` 是非响应式的

如何动态添加根级别的响应式属性【就是对data添加属性】

this.$set(this.someObject,'b',2)

异步更新队列

Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。

如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。

然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。

Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。

例如,当你设置 vm.someData = 'new value',该组件不会立即重新渲染。

当刷新队列时,组件会在下一个事件循环“tick”中更新。

多数情况我们不需要关心这个过程,但是如果你想基于更新后的 DOM 状态来做点什么,这就可能会有些棘手。虽然 Vue.js 通常鼓励开发人员使用“数据驱动”的方式思考,避免直接接触 DOM,但是有时我们必须要这么做。为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用 Vue.nextTick(callback)。这样回调函数将在 DOM 更新完成后被调用。例如:

<div id="example">{{message}}</div>
 var vm = new Vue({
  el: '#example',
  data: {
  message: '123'
  }
 })
 vm.message = 'new message' // 更改数据
 vm.$el.textContent === 'new message' // false
 Vue.nextTick(function () {
  vm.$el.textContent === 'new message' // true
 })

在组件内使用 vm.$nextTick() 实例方法特别方便,因为它不需要全局 Vue,并且回调函数中的 this 将自动绑定到当前的 Vue 实例上:

Vue.component('example', {
  template: '<span>{{ message }}</span>',
  data: function () {
  return {
   message: '未更新'
  }
  },
  methods: {
  updateMessage: function () {
   this.message = '已更新'
   console.log(this.$el.textContent) // => '未更新'
   this.$nextTick(function () {
   console.log(this.$el.textContent) // => '已更新'
   })
  }
  }
 })

因为 $nextTick() 返回一个 Promise 对象,所以你可以使用新的 ES2017 async/await 语法完成相同的事情:

methods: {
updateMessage: async function () {

this.message = '已更新'
console.log(this.$el.textContent) // => '未更新'
await this.$nextTick()
console.log(this.$el.textContent) // => '已更新'
}
}

Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。

$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM

实例化理解Vue响应化

<div id="app">

<div>Price :¥{{ price }}</div>
<div>Total:¥{{ price * quantity }}</div>
<div>Taxes: ¥{{ totalPriceWithTax }}</div>
<button @click="changePrice">改变价格</button>
</div>
var app = new Vue({
el: '#app',
data() {

return {
 price: 5.0,
 quantity: 2
};
},
computed: {

totalPriceWithTax() {
 return this.price * this.quantity * 1.03;
}
},
methods: {

changePrice() {
 this.price = 10;
}
}
})

上例中当price 发生变化的时候,Vue就知道自己需要做三件事情:

  • 更新页面上price的值
  • 计算表达式 price*quantity 的值,更新页面
  • 调用totalPriceWithTax 函数,更新页面

数据发生变化后,会重新对页面渲染,这就是Vue响应式,那么这一切是怎么做到的呢?

想完成这个过程,我们需要:

  • 侦测数据的变化
  • 收集视图依赖了哪些数据
  • 数据变化时,自动“通知”需要更新的视图部分,并进行更新

对应专业俗语分别是:

  • 数据劫持 / 数据代理
  • 依赖收集
  • 发布订阅模式

总结

再来回顾下整个过程:

Vue中this.$nextTick的作用及用法

在new Vue()后, Vue 会调用_init函数进行初始化,也就是init 过程,在 这个过程Data通过Observer转换成了getter/setter的形式,来对数据追踪变化,当被设置的对象被读取的时候会执行getter函数,而在当被赋值的时候会执行setter函数。

当外界通过Watcher读取数据时,会触发getter从而将Watcher添加到依赖中。

在修改对象的值的时候,会触发对应的setter,setter通知之前依赖收集得到的 Dep 中的每一个 Watcher,告诉它们自己的值改变了,需要重新渲染视图。这时候这些 Watcher就会开始调用update来更新视图。

以上就是本次介绍的全部相关知识点内容,如果大家学习中有任何补充可以联系三水点靠木小编。

Javascript 相关文章推荐
Javascript写了一个清除“logo1_.exe”的杀毒工具(可扫描目录)
Feb 09 Javascript
理解Javascript_11_constructor实现原理
Oct 18 Javascript
Jquery下判断Id是否存在的代码
Jan 06 Javascript
js中哈希表的几种用法总结
Jan 28 Javascript
Jquery异步提交表单代码分享
Mar 26 Javascript
js使用onmousemove和onmouseout获取鼠标坐标的方法
Mar 31 Javascript
JavaScript+CSS实现仿天猫侧边网页菜单效果
Aug 25 Javascript
JS基于myFocus库实现各种功能的tab选项卡切换效果
Sep 19 Javascript
跟我学习JScript的Bug与内存管理
Nov 18 Javascript
JS+CSS实现的漂亮渐变背景特效代码(6个渐变效果)
Mar 25 Javascript
使用layer.msg 时间设置不起作用的解决方法
Sep 12 Javascript
Vue页面跳转传递参数及接收方式
Sep 09 Javascript
JS中this的4种绑定规则详解
Feb 04 #Javascript
详解JavaScript中精度失准问题及解决方法
Feb 04 #Javascript
Preload基础使用方法详解
Feb 03 #Javascript
使用PreloadJS加载图片资源的基础方法详解
Feb 03 #Javascript
使用preload预加载页面资源时注意事项
Feb 03 #Javascript
jQuery实现小火箭返回顶部特效
Feb 03 #jQuery
JS常用正则表达式超全集(密码强度校验,金额校验,IE版本,IPv4,IPv6校验)
Feb 03 #Javascript
You might like
Yii2.0 模态弹出框+ajax提交表单
2016/05/22 PHP
laravel 5.3中自定义加密服务的方案详解
2017/05/09 PHP
深入理解Yii2.0乐观锁与悲观锁的原理与使用
2017/07/26 PHP
PHP pthreads v3下同步处理synchronized用法示例
2020/02/21 PHP
PHP safe_mode开启对于PHP系统函数有什么影响
2020/11/10 PHP
JAVASCRIPT实现的WEB页面跳转以及页面间传值方法
2010/05/13 Javascript
Javascript基础知识(二)事件
2014/09/29 Javascript
基于javascript实现判断移动终端浏览器版本信息
2014/12/09 Javascript
javascript实现根据身份证号读取相关信息
2014/12/17 Javascript
jQuery验证插件validation使用指南
2015/04/21 Javascript
JavaScript模块规范之AMD规范和CMD规范
2015/10/27 Javascript
JavaScript实现搜索框的自动完成功能(一)
2016/02/25 Javascript
javascript中去除数组重复元素的实现方法【实例】
2016/04/12 Javascript
vue制作加载更多功能的正确打开方式
2016/10/12 Javascript
JS实现的相册图片左右滚动完整实例
2016/11/23 Javascript
Google 爬虫如何抓取 JavaScript 的内容
2017/04/07 Javascript
JavaScript之事件委托实例(附原生js和jQuery代码)
2017/07/22 jQuery
JavaScript同源策略和跨域访问实例详解
2018/04/03 Javascript
详解vue移动端项目的适配(以mint-ui为例)
2018/08/17 Javascript
vue中子组件的methods中获取到props中的值方法
2018/08/27 Javascript
Vue 中可以定义组件模版的几种方式
2019/08/06 Javascript
[03:21]【TI9纪实】Old Boys
2019/08/23 DOTA
python enumerate函数的使用方法总结
2017/11/15 Python
python pands实现execl转csv 并修改csv指定列的方法
2018/12/12 Python
python圣诞树编写实例详解
2020/02/13 Python
Python进程Multiprocessing模块原理解析
2020/02/28 Python
美国最大的万圣节服装网站:HalloweenCostumes.com
2017/10/12 全球购物
HSRP的含义以及如何工作
2014/09/10 面试题
办公室助理岗位职责
2013/12/25 职场文书
小学生感恩演讲稿
2014/04/25 职场文书
医疗器械售后服务承诺书
2014/05/21 职场文书
企业负责人任命书
2014/06/05 职场文书
2014年乡镇民政工作总结
2014/12/02 职场文书
工程部岗位职责范本
2015/04/11 职场文书
学困生帮扶工作总结
2015/08/13 职场文书
openstack云计算keystone组件工作介绍
2022/04/20 Servers