首页IT科技vue视图更新原理(Vue数据变化后页面更新详细介绍)

vue视图更新原理(Vue数据变化后页面更新详细介绍)

时间2025-04-29 23:47:51分类IT科技浏览3739
导读:首先会通过module.hot.accept监听文件变化,并传入该文件的渲染函数:...

首先会通过module.hot.accept监听文件变化         ,并传入该文件的渲染函数:

随后执行rerender方法                  ,只贴重点部分代码:

record.Ctor.options.render = options.render record.Ctor.options.staticRenderFns = options.staticRenderFns record.instances.slice().forEach(function (instance) { instance.$options.render = options.render instance.$options.staticRenderFns = options.staticRenderFns // reset static trees // pre 2.5, all static trees are cached together on the instance if (instance._staticTrees) { instance._staticTrees = [] } // 2.5.0 if (Array.isArray(record.Ctor.options.cached)) { record.Ctor.options.cached = [] } // 2.5.3 if (Array.isArray(instance.$options.cached)) { instance.$options.cached = [] } // post 2.5.4: v-once trees are cached on instance._staticTrees. // Pure static trees are cached on the staticRenderFns array // (both already reset above) // 2.6: temporarily mark rendered scoped slots as unstable so that // child components can be forced to update var restore = patchScopedSlots(instance) instance.$forceUpdate() instance.$nextTick(restore) })

首先会给当前的VueComponent的Options和实例里面的渲染函数替换为最新     ,然后执行实例上的forceUpdate方法:

Vue.prototype.$forceUpdate = function () { var vm = this; if (vm._watcher) { vm._watcher.update(); } };

该方法是执行watcher实例的update方法:

Watcher.prototype.update = function () { /* istanbul ignore else */ if (this.lazy) { this.dirty = true; } else if (this.sync) { this.run(); } else { queueWatcher(this); } };
function queueWatcher(watcher) { var id = watcher.id; if (has[id] != null) { return; } if (watcher === Dep.target && watcher.noRecurse) { return; } has[id] = true; if (!flushing) { queue.push(watcher); } else { // if already flushing, splice the watcher based on its id // if already past its id, it will be run next immediately. var i = queue.length - 1; while (i > index$1 && queue[i].id > watcher.id) { i--; } queue.splice(i + 1, 0, watcher); } // queue the flush if (!waiting) { waiting = true; if (!config.async) { flushSchedulerQueue(); return; } nextTick(flushSchedulerQueue); } }

重点看 queueWatcher(this)      ,将最新的watcher放入quene队列并且将flushSchedulerQueue函数传给nextTick         。

function nextTick(cb, ctx) { var _resolve; callbacks.push(function () { 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(function (resolve) { _resolve = resolve; }); } }

在callbacks里面放入一个执行回调的函数                  。并执行timerFunc():

timerFunc = function () { p_1.then(flushCallbacks); // In problematic UIWebViews, Promise.then doesnt completely break, but // it can get stuck in a weird state where callbacks are pushed into the // microtask queue but the queue isnt 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); };

该方法异步执行flushCallbacks:

function flushCallbacks() { pending = false; var copies = callbacks.slice(0); callbacks.length = 0; for (var i = 0; i < copies.length; i++) { copies[i](); } }

开始执行回调函数我们第一次放进去的函数flushSchedulerQueue:

function flushSchedulerQueue() { currentFlushTimestamp = getNow(); flushing = true; var watcher, id; // Sort queue before flush. // This ensures that: // 1. Components are updated from parent to child. (because parent is always // created before the child) // 2. A components user watchers are run before its render watcher (because // user watchers are created before the render watcher) // 3. If a component is destroyed during a parent components watcher run, // its watchers can be skipped. queue.sort(sortCompareFn); // do not cache length because more watchers might be pushed // as we run existing watchers for (index$1 = 0; index$1 < queue.length; index$1++) { watcher = queue[index$1]; if (watcher.before) { watcher.before(); } id = watcher.id; has[id] = null; watcher.run(); // in dev build, check and stop circular updates. if (has[id] != null) { circular[id] = (circular[id] || 0) + 1; if (circular[id] > MAX_UPDATE_COUNT) { warn$2(You may have an infinite update loop + (watcher.user ? "in watcher with expression \"".concat(watcher.expression, "\"") : "in a component render function."), watcher.vm); break; } } } // keep copies of post queues before resetting state var activatedQueue = activatedChildren.slice(); var updatedQueue = queue.slice(); resetSchedulerState(); // call component updated and activated hooks callActivatedHooks(activatedQueue); callUpdatedHooks(updatedQueue); // devtool hook /* istanbul ignore if */ if (devtools && config.devtools) { devtools.emit(flush); } }

首先触发watcher.before()                 ,该方法是beforeUpdate的hook     。然后执行watcher.run()方法:

Watcher.prototype.run = function () { if (this.active) { var value = this.get(); if (value !== this.value || // Deep watchers and watchers on Object/Arrays should fire even // when the value is the same, because the value may // have mutated. isObject(value) || this.deep) { // set new value var oldValue = this.value; this.value = value; if (this.user) { var info = "callback for watcher \"".concat(this.expression, "\""); invokeWithErrorHandling(this.cb, this.vm, [value, oldValue], this.vm, info); } else { this.cb.call(this.vm, value, oldValue); } } } };

该方法watcher.get方法        ,该方法会重新执行render方法生成vnode    ,然后调用update方法更新节点:

updateComponent = function () { vm._update(vm._render(), hydrating); };

总结:

1.获取监听文件最新的render和staticRenderFns并赋值给当前的VueComponent和当前vm实例      。

2.使用$forceUpdate添加当前的vm的watcher并在queue中                ,最后异步执行flushSchedulerQueue           ,该函数遍历quene执行watcher的run方法  ,该方法会执行vm实例的_update方法完成更新                 。

到此这篇关于Vue数据变化后页面更新详细介绍的文章就介绍到这了,更多相关Vue页面更新内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

声明:本站所有文章               ,如无特殊说明或标注              ,均为本站原创发布        。任何个人或组织,在未征得本站同意时            ,禁止复制            、盗用              、采集      、发布本站内容到任何网站         、书籍等各类媒体平台    。如若本站内容侵犯了原著者的合法权益                 ,可联系我们进行处理                。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
基于 angular material theming 机制修改 mat-toolbar 的背景色(示例详解) aspnet网站开发技术(aspnet_admin.exe进程是安全的吗 aspnet_admin进程信息查询)