hgq's docs
主页
ES6-阮一峰 (opens new window)
Vue文档 (opens new window)
Axios文档 (opens new window)
Vue Router (opens new window)
Vuex文档 (opens new window)
面试题-Vue (opens new window)
面试题-JS (opens new window)

guoguoqiqi

漫不经心的向往
主页
ES6-阮一峰 (opens new window)
Vue文档 (opens new window)
Axios文档 (opens new window)
Vue Router (opens new window)
Vuex文档 (opens new window)
面试题-Vue (opens new window)
面试题-JS (opens new window)
  • Vue 生命周期
  • v-model 的原理
  • Vue 组件间通信有哪几种方式
  • v-for给每一项加个key的作用
  • v-if与v-show的区别
  • computed 和 watch 的区别
  • 对 SPA 单页面的理解,它的优缺点分别是什么
  • 为什么不建议v-if和v-for一起使用
  • Vue的内置指令
  • MVVM的理解
  • keep-alive 的了解
  • Vue身上set方法的实现原理,为什么能实现视图的更新
  • mixin的用法
  • Vuex 为什么要分模块并且加命名空间
  • vue-router 路由钩子函数是什么 执行顺序是什么
  • Vuex 页面刷新数据丢失怎么解决
  • vue-router的hash和history模式
  • vue-router 路由模式有几种
  • vue-router 中常用的 hash 和 history 路由模式实现原理
  • 动态绑定Class和Style
  • 服务端渲染SSR
  • 对Diff算法的认识
  • 对虚拟DOM的认识
  • 在组件上使用v-model
  • 路由有哪几种导航守卫
  • 在哪个生命周期内调用异步请求
  • 怎么理解Vue中的单向数据流
  • 组件中 data 为什么是一个函数
  • 通过数组下标或者长度无法触发更新
  • 路由懒加载是什么意思
  • 父组件监听子组件的生命周期
  • 父子组件生命周期钩子函数执行顺序
  • Vue项目的SEO优化
  • Vue项目的优化
  • Vue2的响应式原理的基本实现
  • Vue2和Vue3的响应式原理的区别
  • axios简单配置
  • Vuex的使用
  • 相关面试题集合
  • 对函数式组件的认识
  • Vue extend 作用和原理
  • 自定义指令的使用
  • 模板编译的原理
  • Vue是怎样进行依赖收集的
  • Vue生命周期钩子是如何实现的
  • 说明nextTick的原理
    • 请描述组件的渲染流程
    • Vue的普通Slot以及作用域Slot的区别
    • Vue use方法的作用及原理
    • Vue中的修饰符
    • Vue如何兼容ie的问题
    • Vue中style标签的scoped的作用及原理
    • Vue路由传参数
    • Vue事件绑定原理
    • 如何设计一个比较友好的Header组件
    • Vue-router守卫
    • scoped样式穿透
    • Vue是如何重写数组的方法的
    • scoped的情况下无法修改element的样式问题
    • 修改element ui的样式
    • 强制刷新组件的方式有哪些
    • vue组件的设计原则
    • 一个组件的渲染流程
    • 默认插槽、具名插槽和作用域插槽
    • Vue组件的name的作用
    • 为什么Vue被称为“渐进框架”
    • 怎么做Vue项目的SEO优化
    • vue推荐的风格指南
    • 如何重置data
    • vuex中actions和mutations有什么区别
    • 说说你对vue的错误处理的了解
    • 说一说递归组件
    • 对于vue双向数据绑定的理解
    • 说一说vue中template模板的编译过程
    • 说一说nextTick的作用
    • Vue为何采用异步渲染
    • vue-router有几种钩子函数?具体是什么及执行流程是怎样的
    • vue中mixin各个选项的合并策略
    • vue中一个组件模板为什么只能由一个根元素
    • vue中的watch和created哪个先执行
    • vue中编辑页面如果判断是否编辑过并在离开时提示保存
    • vue修饰符sync的作用及原理
    • vue中如何批量引入组件
    • vue使用axios如何取消请求
    • vue项目如何实现国际化(多语言)
    • vue中定义全局方法有哪几种方式
    • 跟keep-alive组件相关的生命周期钩子有哪些
    • 如何响应路由参数变化
    • vue中父子组件生命周期的执行顺序
    • 内置组件keep-alive的实现原理
    • mixins和extends的使用及区别
    • vue自定义指令
    • vue的事件绑定原理
    • vue权限控制一般怎么做
    • vue的动态路由怎么配置使用
    • vuex数据持久化怎么做
    • Vue
    guoguoqiqi
    2022-02-20

    说明nextTick的原理

    # 源码解析

    // core/util/next-tick.js
    
    /* @flow */
    /* globals MutationObserver */
    
    import { noop } from "shared/util";
    import { handleError } from "./error";
    import { isIE, isIOS, isNative } from "./env";
    
    export let isUsingMicroTask = false;
    
    // 全局的一个回调事件队列
    const callbacks = [];
    let pending = false;
    
    // 取出callbacks中的所有事件,挨个执行
    function flushCallbacks() {
    	pending = false;
    	const copies = callbacks.slice(0);
    	callbacks.length = 0;
    	for (let i = 0; i < copies.length; i++) {
    		copies[i]();
    	}
    }
    
    let timerFunc;
    
    // callbacks事件队列执行方式
    // 第一种 Promise,如果支持Promise,那就利用Promise将事件队列里的事件推入微任务队列
    // 第二种 MutationObserver 这个方法是用于监测Dom树的变化,如果Dom树发生变化,可以触发回调函数,也是微任务
    // 第三种 setImmediate 立即执行,可代替 setTimeout(cb, 0) 属于宏任务
    // 第四种 setTimeout 如果上述都不支持,那就用setTimeout 也属于宏任务
    if (typeof Promise !== "undefined" && isNative(Promise)) {
    	const p = Promise.resolve();
    	timerFunc = () => {
    		p.then(flushCallbacks);
    		if (isIOS) setTimeout(noop);
    	};
    	isUsingMicroTask = true;
    } else if (
    	!isIE &&
    	typeof MutationObserver !== "undefined" &&
    	(isNative(MutationObserver) ||
    		MutationObserver.toString() === "[object MutationObserverConstructor]")
    ) {
    	let counter = 1;
    	const observer = new MutationObserver(flushCallbacks);
    	const textNode = document.createTextNode(String(counter));
    	observer.observe(textNode, {
    		characterData: true,
    	});
    	timerFunc = () => {
    		counter = (counter + 1) % 2;
    		textNode.data = String(counter);
    	};
    	isUsingMicroTask = true;
    } else if (typeof setImmediate !== "undefined" && isNative(setImmediate)) {
    	timerFunc = () => {
    		setImmediate(flushCallbacks);
    	};
    } else {
    	timerFunc = () => {
    		setTimeout(flushCallbacks, 0);
    	};
    }
    
    // 看看nextTick方法做了什么
    // 接收两个参数,第一个是回调函数、第二个是上下文对象
    export function nextTick(cb?: Function, ctx?: Object) {
    	let _resolve;
    
    	// 如果传入了回调函数,那么这个回调函数会被添加到那个callbacks事件队列中去
    	// 如果没有传入回调函数,那么会将一个Promise对象添加进去
    	callbacks.push(() => {
    		if (cb) {
    			try {
    				cb.call(ctx);
    			} catch (e) {
    				handleError(e, ctx, "nextTick");
    			}
    		} else if (_resolve) {
    			_resolve(ctx);
    		}
    	});
    	if (!pending) {
    		pending = true;
    		timerFunc();
    	}
    	// $flow-disable-line
    	if (!cb && typeof Promise !== "undefined") {
    		return new Promise((resolve) => {
    			_resolve = resolve;
    		});
    	}
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95

    ← Vue生命周期钩子是如何实现的 请描述组件的渲染流程→

    最近更新
    01
    vuex数据持久化怎么做
    05-22
    02
    vue的动态路由怎么配置使用
    05-22
    03
    vue权限控制一般怎么做
    05-22
    更多文章>
    Theme by Vdoing | Copyright © 2022-2022 Guoquoqiqi | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式