电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

詳解Vue的異步更新實現原理

瀏覽:27日期:2022-10-17 10:47:08

最近面試總是會被問到這么一個問題:在使用vue的時候,將for循環中聲明的變量i從1增加到100,然后將i展示到頁面上,頁面上的i是從1跳到100,還是會怎樣?答案當然是只會顯示100,并不會有跳轉的過程。

怎么可以讓頁面上有從1到100顯示的過程呢,就是用setTimeout或者Promise.then等方法去模擬。

講道理,如果不在vue里,單獨運行這段程序的話,輸出一定是從1到100,但是為什么在vue中就不一樣了呢?

for(let i=1; i<=100; i++){console.log(i);}

這就涉及到Vue底層的異步更新原理,也要說一說nextTick的實現。不過在說nextTick之前,有必要先介紹一下JS的事件運行機制。

JS運行機制

眾所周知,JS是基于事件循環的單線程的語言。 執行的步驟大致是:

當代碼執行時,所有同步的任務都在主線程上執行,形成一個執行棧; 在主線程之外還有一個任務隊列(task queue),只要異步任務有了運行結果就在任務隊列中放置一個事件; 一旦執行棧中所有同步任務執行完畢(主線程代碼執行完畢),此時主線程不會空閑而是去讀取任務隊列。此時,異步的任務就結束等待的狀態被執行。 主線程不斷重復以上的步驟。

詳解Vue的異步更新實現原理

我們把主線程執行一次的過程叫一個tick,所以nextTick就是下一個tick的意思,也就是說用nextTick的場景就是我們想在下一個tick做一些事的時候。

所有的異步任務結果都是通過任務隊列來調度的。而任務分為兩類:宏任務(macro task)和微任務(micro task)。它們之間的執行規則就是每個宏任務結束后都要將所有微任務清空。 常見的宏任務有setTimeout/MessageChannel/postMessage/setImmediate,微任務有MutationObsever/Promise.then。

想要透徹學習事件循環,推薦Jake在JavaScript全球開發者大會的演講,保證講懂!

nextTick原理派發更新

大家都知道vue的響應式的靠依賴收集和派發更新來實現的。在修改數組之后的派發更新過程,會觸發setter的邏輯,執行dep.notify():

// src/core/observer/watcher.jsclass Dep {notify() { //subs是Watcher的實例數組 const subs = this.subs.slice() for(let i=0, l=subs.length; i<l; i++){ subs[i].update() } }}

遍歷subs里每一個Watcher實例,然后調用實例的update方法,下面我們來看看update是怎么去更新的:

class Watcher {update() { ... //各種情況判斷之后 else{ queueWatcher(this) } }}

update執行后又走到了queueWatcher,那就繼續去看看queueWatcher干啥了(希望不要繼續套娃了:

//queueWatcher 定義在 src/core/observer/scheduler.jsconst queue: Array<Watcher> = []let has: { [key: number]: ?true } = {}let waiting = falselet flushing = falselet index = 0export function queueWatcher(watcher: Watcher) {const id = watcher.id //根據id是否重復做優化 if(has[id] == null){ has[id] = true if(!flushing){ queue.push(watcher) }else{ let i=queue.length - 1 while(i > index && queue[i].id > watcher.id){ i-- } queue.splice(i + 1, 0, watcher) } if(!waiting){ waiting = true //flushSchedulerQueue函數: Flush both queues and run the watchers nextTick(flushSchedulerQueue) } }}

這里queue在pushwatcher時是根據id和flushing做了一些優化的,并不會每次數據改變都觸發watcher的回調,而是把這些watcher先添加到⼀個隊列⾥,然后在nextTick后執⾏flushSchedulerQueue。

flushSchedulerQueue函數是保存更新事件的queue的一些加工,讓更新可以滿足Vue更新的生命周期。

這里也解釋了為什么for循環不能導致頁面更新,因為for是主線程的代碼,在一開始執行數據改變就會將它push到queue里,等到for里的代碼執行完畢后i的值已經變化為100時,這時vue才走到nextTick(flushSchedulerQueue)這一步。

nextTick源碼

接著打開vue2.x的源碼,目錄core/util/next-tick.js,代碼量很小,加上注釋才110行,是比較好理解的。

const callbacks = []let pending = falseexport 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() }

首先將傳入的回調函數cb(上節的flushSchedulerQueue)壓入callbacks數組,最后通過timerFunc函數一次性解決。

let timerFuncif (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) || // PhantomJS and iOS 7.x 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) }}

timerFunc下面一大片if else是在判斷不同的設備和不同情況下選用哪種特性去實現異步任務:優先檢測是否原生⽀持Promise,不⽀持的話再去檢測是否⽀持MutationObserver,如果都不行就只能嘗試宏任務實現,首先是setImmediate,這是⼀個⾼版本 IE 和 Edge 才⽀持的特性,如果都不⽀持的話最后就會降級為 setTimeout 0。

這⾥使⽤callbacks⽽不是直接在nextTick中執⾏回調函數的原因是保證在同⼀個 tick 內多次執⾏nextTick,不會開啟多個異步任務,⽽把這些異步任務都壓成⼀個同步任務,在下⼀個 tick 執⾏完畢。

nextTick使用

nextTick不僅是vue的源碼文件,更是vue的一個全局API。下面來看看怎么使用吧。

當設置 vm.someData = ’new value’,該組件不會立即重新渲染。當刷新隊列時,組件會在下一個事件循環tick中更新。多數情況我們不需要關心這個過程,但是如果你想基于更新后的 DOM 狀態來做點什么,這就可能會有些棘手。雖然 Vue.js 通常鼓勵開發人員使用數據驅動的方式思考,避免直接接觸 DOM,但是有時我們必須要這么做。為了在數據變化之后等待 Vue 完成更新 DOM,可以在數據變化之后立即使用Vue.nextTick(callback)。這樣回調函數將在 DOM 更新完成后被調用。

官網用例:

<div id='example'>{{message}}</div>

var vm = new Vue({ el: ’#example’, data: { message: ’123’ }})vm.message = ’new message’ // 更改數據vm.$el.textContent === ’new message’ // falseVue.nextTick(function () { vm.$el.textContent === ’new message’ // true})

并且因為$nextTick() 返回一個 Promise 對象,所以也可以使用async/await 語法去處理事件,非常方便。

以上就是詳解Vue的異步更新實現原理的詳細內容,更多關于vue 異步更新的資料請關注好吧啦網其它相關文章!

標簽: Vue
相關文章:
主站蜘蛛池模板: 全自动变压器变比组别测试仪-手持式直流电阻测试仪-上海来扬电气 | 东莞市踏板石餐饮管理有限公司_正宗桂林米粉_正宗桂林米粉加盟_桂林米粉加盟费-东莞市棒子桂林米粉 | 水冷式工业冷水机组_风冷式工业冷水机_水冷螺杆冷冻机组-深圳市普威机械设备有限公司 | 网站建设,北京网站建设,北京网站建设公司,网站系统开发,北京网站制作公司,响应式网站,做网站公司,海淀做网站,朝阳做网站,昌平做网站,建站公司 | 九州网址_专注于提供网址大全分享推广中文网站导航服务 | 全屋整木定制-橱柜,家具定制-四川峨眉山龙马木业有限公司 | 衬氟旋塞阀-卡套旋塞阀-中升阀门首页| 实战IT培训机构_IT培训班选大学生IT技术培训中心_中公优就业 | 浙江华锤电器有限公司_地磅称重设备_防作弊地磅_浙江地磅售后维修_无人值守扫码过磅系统_浙江源头地磅厂家_浙江工厂直营地磅 | 超声波清洗机_大型超声波清洗机_工业超声波清洗设备-洁盟清洗设备 | 盘装氧量分析仪-防爆壁挂氧化锆分析仪-安徽吉帆仪表有限公司 | led冷热冲击试验箱_LED高低温冲击试验箱_老化试验箱-爱佩百科 | 天津力值检测-天津管道检测-天津天诚工程检测技术有限公司 | 缓蚀除垢剂_循环水阻垢剂_反渗透锅炉阻垢剂_有机硫化物-郑州威大水处理材料有限公司 | 保温杯,儿童婴童奶瓶,运动水壶「广告礼品杯定制厂家」超朗保温杯壶 | 自清洗过滤器-全自动自清洗过反冲洗过滤器 - 中乂(北京)科技有限公司 | 移动厕所租赁|移动卫生间|上海移动厕所租赁-家瑞租赁 | 化工ERP软件_化工新材料ERP系统_化工新材料MES软件_MES系统-广东顺景软件科技有限公司 | 威实软件_软件定制开发_OA_OA办公系统_OA系统_办公自动化软件 | 语料库-提供经典范文,文案句子,常用文书,您的写作得力助手 | 澳门精准正版免费大全,2025新澳门全年免费,新澳天天开奖免费资料大全最新,新澳2025今晚开奖资料,新澳马今天最快最新图库-首页-东莞市傲马网络科技有限公司 | 广东护栏厂家-广州护栏网厂家-广东省安麦斯交通设施有限公司 | 烘箱-工业烘箱-工业电炉-实验室干燥箱 - 苏州华洁烘箱制造有限公司 | 中医治疗皮肤病_潍坊银康医院「山东」重症皮肤病救治平台 | 成都治疗尖锐湿疣比较好的医院-成都治疗尖锐湿疣那家医院好-成都西南皮肤病医院 | 成都珞石机械 - 模温机、油温机、油加热器生产厂家 | H型钢切割机,相贯线切割机,数控钻床,数控平面钻,钢结构设备,槽钢切割机,角钢切割机,翻转机,拼焊矫一体机 | 济南网站建设_济南网站制作_济南网站设计_济南网站建设公司_富库网络旗下模易宝_模板建站 | 广西正涛环保工程有限公司【官网】 | 防火阀、排烟防火阀、电动防火阀产品生产销售商-德州凯亿空调设备有限公司 | 香蕉筛|直线|等厚|弧形|振动筛|香蕉筛厂家-洛阳隆中重工 | 球磨机,节能球磨机价格,水泥球磨机厂家,粉煤灰球磨机-吉宏机械制造有限公司 | 大通天成企业资质代办_承装修试电力设施许可证_增值电信业务经营许可证_无人机运营合格证_广播电视节目制作许可证 | 布袋除尘器|除尘器设备|除尘布袋|除尘设备_诺和环保设备 | 远程会诊系统-手术示教系统【林之硕】医院远程医疗平台 | 云南丰泰挖掘机修理厂-挖掘机维修,翻新,再制造的大型企业-云南丰泰工程机械维修有限公司 | 吉祥新世纪铝塑板_生产铝塑板厂家_铝塑板生产厂家_临沂市兴达铝塑装饰材料有限公司 | 智能化的检漏仪_气密性测试仪_流量测试仪_流阻阻力测试仪_呼吸管快速检漏仪_连接器防水测试仪_车载镜头测试仪_奥图自动化科技 | 新材料分散-高速均质搅拌机-超声波分散混合-上海化烁智能设备有限公司 | 深圳公司注册-工商注册公司-千百顺代理记账公司 | 金联宇电缆|广东金联宇电缆厂家_广东金联宇电缆实业有限公司 |