怎么做微信网站吗,做电子书下载网站会不会侵权,设计师论坛,免费做封面网站Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化#xff0c;Vue 将开启一个队列#xff0c;并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发#xff0c;只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非… Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化Vue 将开启一个队列并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后在下一个的事件循环“tick”中Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate如果执行环境不支持则会采用 setTimeout(fn, 0) 代替。 宏任务scriptsetTimeoutsetIntervalpostMessagemessageChannelsetImmediate 微任务promise.thenObject.observemutationObserverprocess.nextTick。 例如当你设置 vm.someData new value该组件不会立即重新渲染。当刷新队列时组件会在下一个事件循环“tick”中更新。多数情况我们不需要关心这个过程但是如果你想基于更新后的 DOM 状态来做点什么这就可能会有些棘手。虽然 Vue.js 通常鼓励开发人员使用“数据驱动”的方式思考避免直接接触 DOM但是有时我们必须要这么做。为了在数据变化之后等待 Vue 完成更新 DOM可以在数据变化之后立即使用 Vue.nextTick(callback)。这样回调函数将在 DOM 更新完成后被调用。例如 div idexample{{message}}/div
var vm new Vue({el: #example,data: {message: 123}
})
vm.message new message // 更改数据
vm.$el.textContent new message // false
Vue.nextTick(function () {vm.$el.textContent new message // true
})在组件内使用 vm.$nextTick() 实例方法特别方便因为它不需要全局 Vue并且回调函数中的 this 将自动绑定到当前的 Vue 实例上 Vue.component(example, {template: span{{ message }}/span,data: function () {return {message: 未更新}},methods: {updateMessage: function () {this.message 已更新console.log(this.$el.textContent) // 未更新this.$nextTick(function () {console.log(this.$el.textContent) // 已更新})}}
})因为 $nextTick() 返回一个 Promise 对象所以你可以使用新的 ES2017 async/await 语法完成相同的事情 methods: {updateMessage: async function () {this.message 已更新console.log(this.$el.textContent) // 未更新await this.$nextTick()console.log(this.$el.textContent) // 已更新}
}异步只要监听到数据变化了vue就开启一个队列并缓存在同一个时间循环中发生的所有数据变更。 批量如果同一个watcher被多次出发只会被推入到队列中一次。去重对于避免不必要的计算和dom操作非常重要在下一个时间循环tick中vue刷新队列执行实际工作 异步策略vue在内部对异步队列禅师使用原生的Promise.thenmutation observe和setImmediate如果执行环境不支持则会采用setTimeout替代。 this.foo 111
this.foo 222
this.foo 333
触发foo的dep.notify()
notify(){const subs this.subs.slice()for(let i 0;L subs.length;iL;i){subs[i].update() // 触发update方法且执行三遍}
}
class Watcher{update(){queueWatcher(this)}
}nextTick function nextTick(cb, ctx) {callbacks.push(() {cb.call(ctx)})if (!pending) {pending truePromise.resolve().then(flushCallbacks)}
}flushCallbacks function flushCallbacks() {pending falseconst copies callbacks.slice(0)callbacks.length 0for (let i 0; i copies.length; i) {copies[i]()}
}queueWatcher function queueWatcher(watcher) {const id watcher.idif (has[id] ! null) { // 下次有相同id就不再进入return}if (watcher Dep.target watcher.noRecurse) {return}has[id] trueif (!flushing) {queue.push(watcher)} else {let i queue.length - 1while (i index queue[i].id watcher.id) {i--}queue.splice(i 1, 0, watcher)}if (!waiting) {waiting true// 建立一个微任务等当前宏任务执行完毕再执行。nextTick(flushSchedulerQueue)}
} flushSchedulerQueue function flushSchedulerQueue() {currentFlushTimestamp getNow()flushing truelet watcher, idqueue.sort(sortCompareFn)for (index 0; index queue.length; index) {watcher queue[index]if (watcher.before) {watcher.before()}id watcher.idhas[id] nullwatcher.run()}const activatedQueue activatedChildren.slice()const updatedQueue queue.slice()resetSchedulerState()callActivatedHooks(activatedQueue)callUpdatedHooks(updatedQueue)cleanupDeps()
}