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 ...
随机推荐
- @RequestMapping-@PathVariable小误区
去掉勾选就可以演示出错误了,一般勾选是为了方便我们Debug调试 会出现500错误: 正确的写法:
- JS基础_强制类型转换-String
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- spring boot入门与进阶教程
SpringBoot入门.SpringBoot进阶.Spring Cloud微服务.Spring Ecosystem 微服务相关.Spring Boot 入门 IDEA 版本.Spring Boot集 ...
- vue路由公用
大体思路,一个页面,多个按钮,点击按钮后都跳转到一个路由:通过父亲传的值是什么,来决定跳那个路由:ajax数据也是通过判断来决定拉那个数据 路由: export default { routes: [ ...
- window.prompt()和 window.confirm()选择
代码截图: 效果: 代码截图: 效果:
- 深入简出mysql--第一部分
第二章: 1.sql分类 DDL(Data Definition Languages)语句:数据定义语言,这些语句定义了不同的数据段.数据库.表.列.索引等数据库对象的定义. 常用的语句关键字主要包括 ...
- 2019-2020-1 20199319《Linux内核原理与分析》第九周作业
进程的切换和系统的一般执行过程 进程调度的时机 1.中断:起到切出进程指令流的作用.中断处理程序是与进程无关的内核指令流.中断类型: 硬中断:可屏蔽中断和不可屏蔽中断.高电平说明有中断请求. 软中断/ ...
- Ansible安装部署和常用命令,及其主机清单inventory(二)
1.ansible的安装方式 1.1使用yum源安装 yum install ansible -y 1.2使用rpm包安装 https://dl.fedoraproject.org/pub/epel/ ...
- svn使用教程(收藏)
SVN简介: 为什么要使用SVN? 程序员在编写程序的过程中,每个程序员都会生成很多不同的版本,这就需要程序员有效的管理代码,在需要的时候可以迅速,准确取出相应的版本. Subversion是什么? ...
- redis 加锁与释放锁(分布式锁1)
使用Redis的 SETNX 命令可以实现分布式锁 SETNX key value 返回值 返回整数,具体为 - 1,当 key 的值被设置 - 0,当 key 的值没被设置 分布式锁使用 impor ...