VUE异步更新DOM - 用$nextTick解决DOM视图的问题


Posted in Javascript onNovember 06, 2020

VUE异步更新DOM

首先,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数据更新视图不更新,你必须知道的几种解决方案

知识拓展

在一个组件实例中,只有在data里初始化的数据才是响应的,Vue不能检测到对象属性的添加或删除,没有在data里声明的属性不是响应的。

Vue不允许在已经创建的实例上动态添加根级响应式属性,但是可以使用$set方法将相应属性添加到嵌套的对象上。

数组数据变动,使用某些方法操作数组,变动数据时,有些方法无法被vue监测

push(),pop(),shift(),unshift(),splice(),sort(),reverse()可被vue检测到

filter(), concat(), slice()。这些不会改变原始数组,但总是返回一个新数组。当使用非变异方法时,可以用新数组替换旧数组。

vue不能检测以下变动的数组:

1、当你利用索引直接设置一个项时,vm.items[indexOfItem] = newValue

2、当你修改数组的长度时,例如: vm.items.length = newLength

对象属性的添加或删除

由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。

解决办法:

使用 Vue.set(object, key, value) 方法将响应属性添加到嵌套的对象上

Vue.set(vm.someObject, 'b', 2) 或者 this.$set(this.someObject,'b',2) (这也是全局 Vue.set 方法的别名)

异步更新队列

在最新的项目中遇到了这种情况,数据第一次获取到了,也渲染了,但是第二次之后数据只有在再一次渲染页面的时候更新,并不能实时更新。

网上查了资料才知道,Vue 异步执行 DOM 更新。只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。

解决办法:

可在数据变化之后立即使用 Vue.nextTick(callback)。这样回调函数在 DOM 更新完成后就会调用。例如:

VUE异步更新DOM - 用$nextTick解决DOM视图的问题

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

VUE异步更新DOM - 用$nextTick解决DOM视图的问题

Object.assign方法

object.assign方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,并返回目标对象。

vm.object = Object.assign( { } , vm.object , {a:' 1 ', b:' 2 ' })

注:object必须是已经声明的对象

vue多层循环,动态改变数据后渲染的很慢或者不渲染

可在动态改变数据的方法,第一行加上

this.$forceUpdate();

以上这篇VUE异步更新DOM - 用$nextTick解决DOM视图的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript中的var_dump函数实现代码
Sep 07 Javascript
有效的捕获JavaScript焦点的方法小结
Oct 08 Javascript
不用锚点也可以平滑滚动到页面的指定位置实现代码
May 08 Javascript
JQuery中dataGrid设置行的高度示例代码
Jan 03 Javascript
JavaScript字符串对象substring方法入门实例(用于截取字符串)
Oct 17 Javascript
Bootstrap Table的使用总结
Oct 08 Javascript
Bootstrap如何创建表单
Oct 21 Javascript
js判断手机号是否正确并返回的实现代码
Jan 17 Javascript
js与jQuery实现的用户注册协议倒计时功能实例【三种方法】
Nov 09 jQuery
跨域请求两种方法 jsonp和cors的实现
Nov 11 Javascript
vue搜索和vue模糊搜索代码实例
May 07 Javascript
javascript实现京东登录显示隐藏密码
Aug 02 Javascript
nuxt.js服务端渲染中axios和proxy代理的配置操作
Nov 06 #Javascript
微信小程序开发数据缓存基础知识辨析及运用实例详解
Nov 06 #Javascript
nuxt 路由、过渡特效、中间件的实现代码
Nov 06 #Javascript
Nuxt的路由动画效果案例
Nov 06 #Javascript
微信小程序中target和currentTarget的区别小结
Nov 06 #Javascript
vue router-link 默认a标签去除下划线的实现
Nov 06 #Javascript
微信小程序调用后台service教程详解
Nov 06 #Javascript
You might like
国外十大最流行的PHP框架排名
2013/07/04 PHP
thinkPHP框架实现的短信接口验证码功能示例
2018/06/20 PHP
php实现商城购物车的思路和源码分析
2020/07/23 PHP
一个无限级XML绑定跨框架菜单(For IE)
2007/01/27 Javascript
从新浪弄下来的全屏广告代码 与使用说明
2007/03/15 Javascript
jqPlot 基于jquery的画图插件
2011/04/26 Javascript
javascript实现2048游戏示例
2014/05/04 Javascript
JavaScript组件焦点与页内锚点间传值的方法
2015/02/02 Javascript
jQuery选择器源码解读(六):Sizzle选择器匹配逻辑分析
2015/03/31 Javascript
jQuery结合AJAX之在页面滚动时从服务器加载数据
2015/06/30 Javascript
学习JavaScript设计模式之享元模式
2016/01/18 Javascript
jQuery移动端日期(datedropper)和时间(timedropper)选择器附源码下载
2016/04/19 Javascript
checkbox 选中一个另一个checkbox也会选中的实现代码
2016/07/09 Javascript
JS动态添加选项案例分析
2016/10/17 Javascript
Angular 4依赖注入学习教程之ValueProvider的使用(七)
2017/06/04 Javascript
json字符串传到前台input的方法
2018/08/06 Javascript
详解mpvue scroll-view自动回弹bug解决方案
2018/10/01 Javascript
bootstrap-table formatter 使用vue组件的方法
2019/05/09 Javascript
使用webpack/gulp构建TypeScript项目的方法示例
2019/12/18 Javascript
VUE+elementui组件在table-cell单元格中绘制微型echarts图
2020/04/20 Javascript
[01:05:56]2018DOTA2亚洲邀请赛3月29日 小组赛A组 Newbee VS VG
2018/03/30 DOTA
横向对比分析Python解析XML的四种方式
2016/03/30 Python
Django应用程序中如何发送电子邮件详解
2017/02/04 Python
python用BeautifulSoup库简单爬虫实例分析
2018/07/30 Python
浅谈Django的缓存机制
2018/08/23 Python
Pandas透视表(pivot_table)详解
2019/07/22 Python
PyQt5通信机制 信号与槽详解
2019/08/07 Python
Python 继承,重写,super()调用父类方法操作示例
2019/09/29 Python
公共汽车、火车和飞机票的通用在线预订和销售平台:INFOBUS
2019/11/30 全球购物
教你怎样写好自我评价
2013/10/05 职场文书
农业局学习党的群众路线教育实践活动心得体会
2014/03/07 职场文书
会计系毕业生求职信
2014/05/28 职场文书
酒店管理失职检讨书
2014/09/16 职场文书
医院党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
六查六看自检自查剖析材料
2014/10/14 职场文书
pytorch中的model=model.to(device)使用说明
2021/05/24 Python