Vue源码阅读一:说说vue.nextTick实现
用法:
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
疑惑:
怎么实现的延迟回调
原理:
- JavaScript语言的一大特点就是单线程,同一个时间只能做一件事
- JavaScript任务可以分为两种,一种是同步任务,一种是异步任务
- 异步任务大致分为,宏任务,和微任务
- 所有同步任务都在主线程上执行,形成一个执行栈
- 主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
- 一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列"中的微任务,其次是宏任务,看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
- 主线程不断重复上面的第6步。
vue实现:
vue 大多数情况下优先使用微任务, 很少的地方使用宏任务
vue nextTick 宏任务实现
- 优先检测 setImmediate
if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
macroTimerFunc = () => {
setImmediate(flushCallbacks)
}
}
setImmediate 浏览器支持情况

- 其次检测 MessageChannel 支持情况
else if (typeof MessageChannel !== 'undefined' && (
isNative(MessageChannel) ||
// PhantomJS
MessageChannel.toString() === '[object MessageChannelConstructor]'
)) {
const channel = new MessageChannel()
const port = channel.port2
channel.port1.onmessage = flushCallbacks
macroTimerFunc = () => {
port.postMessage(1)
}
}
MessageChannel 浏览器支持情况

- 上面都不支持就使用最原始的setTimeout
else {
/* istanbul ignore next */
macroTimerFunc = () => {
setTimeout(flushCallbacks, 0)
}
}
vue nextTick 微任务实现
- 优先检测 Promise
if (typeof Promise !== 'undefined' && isNative(Promise)) {
const p = Promise.resolve()
microTimerFunc = () => {
p.then(flushCallbacks)
// in problematic UIWebViews, Promise.then doesn't completely break, but
// it can get stuck in a weird state where callbacks are pushed into the
// microtask queue but the queue isn't being flushed, until the browser
// needs to do some other work, e.g. handle a timer. Therefore we can
// "force" the microtask queue to be flushed by adding an empty timer.
if (isIOS) setTimeout(noop)
}
}
Promise 浏览器支持情况

- 如果不支持Promise, 还是使用宏任务
else {
// fallback to macro
microTimerFunc = macroTimerFunc
}
vue中什么地方用宏任务,什么地方用微任务?
从源码中可以看出,在DOM事件中使用Vue.nextTick 默认使用宏任务, 其他地方使用Vue.nextTick默认使用微任务。
其实从源码中注释中可以看出Vue最开始都是使用微任务方式,后面出现了bug,才引入了宏任务方式
// Here we have async deferring wrappers using both microtasks and (macro) tasks.
// In < 2.4 we used microtasks everywhere, but there are some scenarios where
// microtasks have too high a priority and fire in between supposedly
// sequential events (e.g. #4521, #6690) or even between bubbling of the same
// event (#6566). However, using (macro) tasks everywhere also has subtle problems
// when state is changed right before repaint (e.g. #6813, out-in transitions).
// Here we use microtask by default, but expose a way to force (macro) task when
// needed (e.g. in event handlers attached by v-on).
产考资料:
JavaScript 运行机制详解:再谈Event Loop
Vue源码阅读一:说说vue.nextTick实现的更多相关文章
- Vue源码分析(一) : new Vue() 做了什么
Vue源码分析(一) : new Vue() 做了什么 author: @TiffanysBear 在了解new Vue做了什么之前,我们先对Vue源码做一些基础的了解,如果你已经对基础的源码目录设计 ...
- [Vue源码]一起来学Vue模板编译原理(二)-AST生成Render字符串
本文我们一起通过学习Vue模板编译原理(二)-AST生成Render字符串来分析Vue源码.预计接下来会围绕Vue源码来整理一些文章,如下. 一起来学Vue双向绑定原理-数据劫持和发布订阅 一起来学V ...
- [Vue源码]一起来学Vue模板编译原理(一)-Template生成AST
本文我们一起通过学习Vue模板编译原理(一)-Template生成AST来分析Vue源码.预计接下来会围绕Vue源码来整理一些文章,如下. 一起来学Vue双向绑定原理-数据劫持和发布订阅 一起来学Vu ...
- [Vue源码]一起来学Vue双向绑定原理-数据劫持和发布订阅
有一段时间没有更新技术博文了,因为这段时间埋下头来看Vue源码了.本文我们一起通过学习双向绑定原理来分析Vue源码.预计接下来会围绕Vue源码来整理一些文章,如下. 一起来学Vue双向绑定原理-数据劫 ...
- vue源码阅读(一)
版本:2.5.17-beta.0 核心模块(src/core):包括组件.全局API.vue实例.对象属性监测系统.公共方法.虚拟dom.配置等模块 src/core/index.js import ...
- vue源码阅读(二)
一 一个实例 如果简单了解过些Vue的API的话,肯定会对一下这个特别熟悉,在上一篇里,分析了Vue的核心文件core的index.js构造vue函数执行的流程. 那么下边这个则是实例化构造函数,也就 ...
- vue 源码阅读记录
0.webpack默认引入的是vue.runtime.common.js,并不是vue.js,功能有略微差别,不影响使用 1.阅读由ts编译后的js: 入口>构造函数 >定义各类方法 &g ...
- vue源码阅读笔记
1.yarn test [文件名] -t [name-of-spec(describe or test )] 直接运行yarn test,会测试所有测试文件:yarn test 后面只跟文件名的话会 ...
- vue源码分析之new Vue过程
实例化构造函数 从这里可以看出new Vue实际上是使vue构造函数实例化,然后调用_init方法 _init方法,该方法在 src/core/instance/init.js 中定义 Vue.pro ...
随机推荐
- easyui在table单元格中添加进度条
function XR_jd(alue, rowData, rowIndex){ var value; ...... var htmlstr = '<div class="easyui ...
- 导出excel-模版
后台代码 public void ToExcel(){ //第一步:获取模版文件物理路径 string file_0 = Server.MapPath("/Content/Excel/Exp ...
- Jquery table相关--工时系统
1.jquery 的弹出对话框,单击事件之后 if (confirm("确定要删除?")) { // //点击确定后操作 } 2.对某个table中的checkbox是否被选中的遍 ...
- L2Dwidget.js L2D网页动画人物添加
hexo 添加live2d看板动画 https://www.jianshu.com/p/3a6342e16e57 首先贴出官网代码 官网地址配置:https://www.npmjs.com/packa ...
- python进阶资源
本文为不同阶段的Python学习者从不同角度量身定制了49个学习资源. 初学者 Welcome to Python.org https://www.python.org/ 官方Python站点提供了一 ...
- Chrome中的插件运用
1. Postman Java后台开发RPC,还没有没有开始和前端联调,只是想自测下这个RPC,但是有时候RPC的访问入参数据量很大,远远超过get方式访问2k(大多数浏览器通常都会限制url长度在2 ...
- vue + mixin混入对象使用
vue提供的混入对象mixin,类似于一个公共的组件,其他任何组件都可以使用它.我更经常的是把它当成一个公共方法来使用 在项目中有些多次使用的data数据,method方法,或者自定义的vue指令都可 ...
- 多个分组树分别实现单选jq+angular
$scope.seletedGroup=[];var $li=$("#departmentsContainer>ol>li");$.each($li,function( ...
- mysql数据库查询过程探究和优化建议
查询过程探究 我们先看一下向mysql发送一个查询请求时,mysql做了什么? 如上图所示,查询执行的过程大概可分为6个步骤: 客户端向MySQL服务器发送一条查询请求 服务器首先检查查询缓存,如果命 ...
- PAT Basic 1008 数组元素循环右移问题 (20 分)
一个数组A中存有N(>)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(≥)个位置,即将A中的数据由(A0A1⋯AN−1)变换为(AN−M⋯AN−1A ...