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 相关文章推荐
Web层改进II-用xmlhttp 无声息提交复杂表单
Jan 22 Javascript
使用jscript实现二进制读写脚本代码
Jun 09 Javascript
jQuery的实现原理的模拟代码 -3 事件处理
Aug 03 Javascript
window.dialogArguments 使用说明
Apr 11 Javascript
js实现俄罗斯方块小游戏分享
Jan 31 Javascript
JavaScript中的call方法和apply方法使用对比
Aug 12 Javascript
将JavaScript的jQuery库中表单转化为JSON对象的方法
Nov 17 Javascript
JavaScript正则表达式小结(test|match|search|replace|split|exec)
Dec 08 Javascript
Bootstrap CSS布局之代码
Dec 17 Javascript
Vue安装浏览器开发工具的步骤详解
May 12 Javascript
Vue.js中该如何自己维护路由跳转记录
May 19 Javascript
layui 解决富文本框form表单提交为空的问题
Oct 26 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
windows下配置php5.5开发环境及开发扩展
2014/12/25 PHP
php在线解压ZIP文件的方法
2014/12/30 PHP
浅析PHP7新功能及语法变化总结
2016/06/17 PHP
PHP实现mysqli批量执行多条语句的方法示例
2017/07/22 PHP
PHP排序算法之冒泡排序(Bubble Sort)实现方法详解
2018/04/20 PHP
PHP文件操作实例总结【文件上传、下载、分页】
2018/12/08 PHP
用javascript实现无刷新更新数据的详细步骤 asp
2006/12/26 Javascript
flexigrid 参数说明
2010/11/23 Javascript
js对象继承之原型链继承实例
2015/01/10 Javascript
百度地图api如何使用
2015/08/03 Javascript
AngularJS equal比较对象实例详解
2016/09/14 Javascript
jquery mobile实现可折叠的导航按钮
2017/03/11 Javascript
详解用node搭建简单的静态资源管理器
2017/08/09 Javascript
原生JS实现的自动轮播图功能详解
2018/12/28 Javascript
vue 项目接口管理的实现
2019/01/17 Javascript
js实现的在本地预览图片功能示例
2019/11/09 Javascript
vue实现图书管理系统
2020/12/29 Vue.js
[01:02:54]完美世界DOTA2联赛PWL S2 FTD vs GXR 第一场 11.22
2020/11/26 DOTA
Python 26进制计算实现方法
2015/05/28 Python
Pycharm保存不能自动同步到远程服务器的解决方法
2019/06/27 Python
python按键按住不放持续响应的实例代码
2019/07/17 Python
Python CSV文件模块的使用案例分析
2019/12/21 Python
python FTP批量下载/删除/上传实例
2019/12/22 Python
解决python 读取 log日志的编码问题
2019/12/24 Python
Django restful framework生成API文档过程详解
2020/11/12 Python
selenium与xpath之获取指定位置的元素的实现
2021/01/26 Python
python上下文管理器异常问题解决方法
2021/02/07 Python
科室工作的个人自我评价
2013/10/30 职场文书
软件部经理岗位职责范本
2014/02/25 职场文书
小学趣味运动会加油稿
2014/09/25 职场文书
公安四风对照检查材料思想汇报
2014/10/11 职场文书
2014年小学图书室工作总结
2014/12/09 职场文书
五年级下册复习计划
2015/01/19 职场文书
高中体育课教学反思
2016/02/16 职场文书
Nginx的rewrite模块详解
2021/03/31 Servers
Python利用FlashText算法实现替换字符串
2022/03/31 Python