语法
Vue.nextTick( [callback, context] )
- 参数:
{Function} [callback]
{Object} [context]
- 用法:
- 在下次
DOM
更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM
1 2 3 4 5 6
| // 修改数据 vm.msg = 'Hello' // DOM 还没有更新 Vue.nextTick(function () { // DOM 更新了 })
|
2.1.0起新增:如果没有提供回调且在支持 Promise
的环境中,则返回一个 Promise
。请注意 Vue
不自带 Promise
的 polyfill
,所以如果你的目标浏览器不原生支持 Promise
(IE
:你们都看我干嘛),你得自己提供 polyfill
。
异步更新队列
Vue
在更新 DOM
时是异步执行的
- 只要侦听到数据变化,
Vue
将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更
- 在缓冲时去除重复数据对于避免不必要的计算和
DOM
操作是非常重要的。然后,在下一个的事件循环tick
中更新
- 如果同一个
watcher
被多次触发,只会被推入到队列中一次
Vue
在内部对异步队列尝试使用原生的 Promise.then
、MutationObserver
和 setImmediate
,如果执行环境不支持,则会采用 setTimeout(fn, 0)
代替
v2.6.12
之next-tick
源码
辅助方法
1 2 3 4 5 6 7 8 9 10
| export const isIE = UA && /msie|trident/.test(UA)
export function noop (a?: any, b?: any, c?: any) {}
export function isNative (Ctor: any): boolean { return typeof Ctor === 'function' && /native code/.test(Ctor.toString()) }
export const isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios')
|
next-tick.js
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 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
import { noop } from 'shared/util' import { handleError } from './error' import { isIE, isIOS, isNative } from './env'
export let isUsingMicroTask = false
const callbacks = []
let pending = false
function flushCallbacks () { pending = false const copies = callbacks.slice(0) callbacks.length = 0 for (let i = 0; i < copies.length; i++) { copies[i]() } }
let timerFunc
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) } }
export function nextTick (cb?: Function, ctx?: Object) { let _resolve callbacks.push(() => { if (cb) { try { cb.call(ctx) } catch (e) { handleError(e, ctx, 'nextTick') } } else if (_resolve) { _resolve(ctx) } }) if (!pending) { pending = true timerFunc() } if (!cb && typeof Promise !== 'undefined') { return new Promise(resolve => { _resolve = resolve }) } }
|
MutationObserver
MutationObserver
接口提供了监视对DOM
树所做更改的能力。
- 它被设计为旧的
Mutation Events
功能的替代品,该功能是DOM3 Events
规范的一部分。
childList:
子节点的变动(指新增,删除或者更改)。
attributes:
属性的变动。
characterData:
节点内容或节点文本的变动。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function flushCallbacks (mutationsList, observer) { console.log("flushCallbacks",{ mutationsList, observer }); } let counter = 1 const observer = new MutationObserver(flushCallbacks) const textNode = document.createTextNode(String(counter)) observer.observe(textNode, { characterData: true })
textNode.data = String(counter);
observer.disconnect();
|
相关链接
- Vue-nextTick
- 异步更新队列
- v2.6.12/src/core/util/next-tick