当前位置:首页 > 日记 > 正文

vue之nextTick全面解析

vue之nextTick全面解析

简介

vue是非常流行的框架,他结合了angular和react的优点,从而形成了一个轻量级的易上手的具有双向数据绑定特性的mvvm框架。本人比较喜欢用之。在我们用vue时,我们经常用到一个方法是this.$nextTick,相信你也用过。我常用的场景是在进行获取数据后,需要对新视图进行下一步操作或者其他操作时,发现获取不到dom。因为赋值操作只完成了数据模型的改变并没有完成视图更新。在这个时候我们需要用到本章介绍的函数。

为什么要用nextTick

请看如下一段代码

new Vue({ el: '#app', data: {  list: [] }, mounted: function () {  this.get() }, methods: {  get: function () {   this.$http.get('/api/article').then(function (res) {    this.list = res.data.data.list    // ref list 引用了ul元素,我想把第一个li颜色变为红色    this.$refs.list.getElementsByTagName('li')[0].style.color = 'red'   })  }, }})

我在获取到数据后赋值给数据模型中list属性,然后我想引用ul元素找到第一个li把它的颜色变为红色,但是事实上,这个要报错了,我们知道,在执行这句话时,ul下面并没有li,也就是说刚刚进行的赋值操作,当前并没有引起视图层的更新。因此,在这样的情况下,vue给我们提供了$nextTick方法,如果我们想对未来更新后的视图进行操作,我们只需要把要执行的函数传递给this.$nextTick方法,vue就会给我们做这个工作。

源码解读

这个函数很简单,vue2.2.6版本 450行开始。

首先,这个函数是采用了一个单利模式还是什么创建的一个闭包函数

var callbacks = [];  // 缓存函数的数组var pending = false; // 是否正在执行var timerFunc; // 保存着要执行的函数

首先定义了一些变量供之后使用,下面是一个函数

function nextTickHandler () { pending = false; // 拷贝出函数数组副本 var copies = callbacks.slice(0); // 把函数数组清空 callbacks.length = 0; // 依次执行函数 for (var i = 0; i < copies.length; i++) {  copies[i](); }}

这个函数就是$nextTick内实际调用的函数。

接下来,是vue分了三种情况来延迟调用以上这个函数,因为$nextTick目的就是把传进来的函数延迟到dom更新后再使用,所以这里依次优雅降序的使用js的方法来做到这一点。

1. promise.then延迟调用

if (typeof Promise !== 'undefined' && isNative(Promise)) { var p = Promise.resolve(); var logError = function (err) { console.error(err); }; timerFunc = function () {  p.then(nextTickHandler).catch(logError);  if (isIOS) { setTimeout(noop); } };}

如果浏览器支持Promise,那么就用Promise.then的方式来延迟函数调用,Promise.then方法可以将函数延迟到当前函数调用栈最末端,也就是函数调用栈最后调用该函数。从而做到延迟。

2. MutationObserver 监听变化

else if (typeof MutationObserver !== 'undefined' && ( isNative(MutationObserver) || MutationObserver.toString() === '[object MutationObserverConstructor]')) { var counter = 1; var observer = new MutationObserver(nextTickHandler); var textNode = document.createTextNode(String(counter)); observer.observe(textNode, {  characterData: true }); timerFunc = function () {  counter = (counter + 1) % 2;  textNode.data = String(counter); };}

MutationObserver是h5新加的一个功能,其功能是监听dom节点的变动,在所有dom变动完成后,执行回调函数。

具体有一下几点变动的监听

  1. childList:子元素的变动
  2. attributes:属性的变动
  3. characterData:节点内容或节点文本的变动
  4. subtree:所有下属节点(包括子节点和子节点的子节点)的变动

可以看出,以上代码是创建了一个文本节点,来改变文本节点的内容来触发的变动,因为我们在数据模型更新后,将会引起dom节点重新渲染,所以,我们加了这样一个变动监听,用一个文本节点的变动触发监听,等所有dom渲染完后,执行函数,达到我们延迟的效果。

3.setTimeout延迟器

else {  timerFunc = function () {   setTimeout(nextTickHandler, 0);  }; }

利用setTimeout的延迟原理,setTimeout(func, 0)会将func函数延迟到下一次函数调用栈的开始,也就是当前函数执行完毕后再执行该函数,因此完成了延迟功能。

闭包函数

 return function queueNextTick (cb, ctx) {  var _resolve;  callbacks.push(function () {   if (cb) { cb.call(ctx); }   if (_resolve) { _resolve(ctx); }  });  // 如果没有函数队列在执行才执行  if (!pending) {   pending = true;   timerFunc();  }  // promise化  if (!cb && typeof Promise !== 'undefined') {   console.log('进来了')   return new Promise(function (resolve) {    _resolve = resolve;   })  } }

这个return的函数就是我们实际使用的闭包函数,每一次添加函数,都会想callbacks这个函数数组入栈。然后监听当前是否正在执行,如果没有,执行函数。这个很好理解。下面一个if是promise化。

this.$nextTick(function () {})// promise化this.$nextTick().then(function () {}.bind(this))

以上代码中第二种写法我们不常见把,直接调用$nextTick函数然后用promise格式去书写代码,不过这个then里面需要手动绑定this,vue内部没有给做处理。

结尾

这就是一个this.$nextTick的实现,其中利用了优雅降序的巧妙手法,使代码尽可能优化。而且还提供了promise的写法,虽然我们不经常用,但是有总比没有好。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

相关文章

WEB服务器系统盘权限简单设置

WEB服务器系统盘权限简单设置

系统盘,服务器,权限,设置,简单,其实网上已经很多这样的文章了,但是我遇到的情况用网上的方法不好用,这几天弄我那服务器弄的脑袋都大了,总出问题 昨天ASP又连接不到MDB了,在网上找了好多资料 问了好多人,最开始时候先是把ASP程序问题排除…

PHP判断FORM表单或URL参数来的数据

PHP判断FORM表单或URL参数来的数据

表单,数据,参数,方法,整数,PHP判断FORM表单或URL参数来的数据是否为整数,is_int函数对于FORM表单或URL参数过来的数据是没有办法判断是否是整数的,因为FORM过来的是字符串。用is_numeric可以判断是否为数字类型,再判断是否有小数点就可以判断…

QQ语音怎么转换成文字qq语音转化为

QQ语音怎么转换成文字qq语音转化为

文字,语音,方法,转换成,转化为,  当你在电脑或手机端登录QQ后,不方便接听语音消息时该怎么办呢?大家一定会想着如何将QQ语音转换成文字消息吧?虽说可以转换,但前提是对方给你发送的是普通话语音消息哦!如果说的家乡话,QQ系统可没那么智能翻…

WPS文字怎么实现文章中局部式的分

WPS文字怎么实现文章中局部式的分

文字,局部,文章,电脑软件,WPS,  很多人都看见过文章分栏的效果,给大家推荐的是一种&ldquo;局部式&rdquo;的分栏,何为&ldquo;局部式&rdquo;,就是将我们整片文章中的一部分文字来进行分栏。以下是小编为您带来的关于WPS文字实现文章中局部式的…

Windows Server 2003服务器重启IIS

Windows Server 2003服务器重启IIS

故障,服务器,步骤,重启,方法,在Windows Server 2003服务器中,很多IIS故障可以通过重新启动的方法加以解决。经过重新启动IIS服务,很多问题(甚至表面看起来比较严重的问题)一般都可以排除。这是因为重新启动IIS服务可以强迫系统重置IIS进程的内…

react.js 父子组件数据绑定实时通

react.js 父子组件数据绑定实时通

实时通讯,数据绑定,组件,示例代码,父子,react.js我自己还在摸索学习中,碰到父子组件数据绑定实时通讯的问题,研究了一下,分享给大家,也给自己留个笔记:import React,{Component} from 'react'import ReactDOM from 'react-dom'class ChildCo…

jQuery滚动插件scrollable.js用法

jQuery滚动插件scrollable.js用法

插件,电脑软件,jQuery,js,scrollable,本文实例讲述了jQuery滚动插件scrollable.js用法。分享给大家供大家参考,具体如下:Scrollable是一个灵活、轻量级用于创建滚动内容的jQuery插件。任何内容(HTML、视频、文件、图片等...)都可以作为一个滚动…

ppt中怎么播放多种格式的视频

ppt中怎么播放多种格式的视频

多种,格式,视频,电脑软件,ppt,  ppt中怎么播放多种格式的视频?我们在ppt中插入视频文件的方法都是点击菜单栏--插入,然后把本地视频上传进去。不过这样的方法也不全面,有些格式的视频传上去并不能播放。下面小编就教你ppt中播放多种格式的…

APACHE支持.htaccess方法

APACHE支持.htaccess方法

方法,支持,电脑软件,APACHE,htaccess,如何让自己的本地APACHE服务器支持".htaccess"呢?其实只要简单修改一下apache的httpd.conf设置就可以让APACHE支持.htaccess了,来看看操作打开httpd.conf文件(在那里? APACHE目录的CONF目录里面),用…

如何在excel表中求和

如何在excel表中求和

如何在,电脑软件,excel,本文简单讲诉3种方法操作excel表中数据的求和使用鼠标选中需要求和的单元格数据使用键盘上面的alt加=号组合键,一起按下组合快捷键后,单元格最后一行显示数据和也可以直接使用鼠标选中所有求和数据后,在表格底部左下方…

解决AJAX请求中含有数组的办法

解决AJAX请求中含有数组的办法

数组,请求,办法,中含有,电脑软件,大家应该都发现了当我们发送AJAX请求的数据中带有数组时,是不能像普通JSON数据一样,直接放在data里发送给后台比如有这样一个数据需要发送给后台:{ "orderId": 22, "resourceJson": [ { "carCa…

浅谈PHP中类和对象的相关函数

浅谈PHP中类和对象的相关函数

函数,类和对象,浅谈,电脑软件,PHP,class_exists 判断一个类是否存在,参数为一个名字!interface_exists 判断一个接口是否存在,参数也是为一个名字!method_exists 判断一个方法是否存在!需要两个:第一个对象变量,第二个是一个方法名! 返回一个布尔值…