成人怡红院-成人怡红院视频在线观看-成人影视大全-成人影院203nnxyz-美女毛片在线看-美女免费黄

站長(zhǎng)資訊網(wǎng)
最全最豐富的資訊網(wǎng)站

淺析Angular變更檢測(cè)中的DOM更新機(jī)制

淺析Angular變更檢測(cè)中的DOM更新機(jī)制

前端(vue)入門到精通課程,老師在線輔導(dǎo):聯(lián)系老師
Apipost = Postman + Swagger + Mock + Jmeter 超好用的API調(diào)試工具:點(diǎn)擊使用

變更檢測(cè)是Angular中很重要的一部分,也就是模型和視圖之間保持同步。在日常開發(fā)過(guò)程中,我們無(wú)需了解變更檢測(cè),因?yàn)锳ngular都幫我們完成了這一部分工作,讓開發(fā)人員更加專注于業(yè)務(wù)實(shí)現(xiàn),提高開發(fā)效率和開發(fā)體驗(yàn)。但是如果想要深入使用框架,或者想要寫出高性能的代碼而不僅僅只是實(shí)現(xiàn)了功能,就必須要去了解變更檢測(cè),它可以幫助我們更好的理解框架,調(diào)試錯(cuò)誤,提高性能等。【相關(guān)教程推薦:《angular教程》】

Angular的DOM更新機(jī)制

我們先來(lái)看一個(gè)小例子。

淺析Angular變更檢測(cè)中的DOM更新機(jī)制

當(dāng)我們點(diǎn)擊按鈕的時(shí)候,改變了name屬性,同時(shí)DOM自動(dòng)被更新成新的name值。

那現(xiàn)在有一個(gè)問(wèn)題,如果我改變name的值后,緊接著把DOM中的innerText輸出出來(lái),它會(huì)是什么值呢?

import { Component, ViewChild, ElementRef } from '@angular/core';  @Component({   selector: 'my-app',   templateUrl: './app.component.html',   styleUrls: [ './app.component.css' ] }) export class AppComponent  {   name = 'Empty';    @ViewChild('textContainer') textContainer: ElementRef;    normalClick(): void {     this.name = 'Hello Angular';      console.log(this.textContainer.nativeElement.innerText);   } }
登錄后復(fù)制

你答對(duì)了嗎?

那這兩段代碼中到底發(fā)生了什么呢?

如果我們用原生JS來(lái)編寫這段代碼,那么點(diǎn)擊按鈕后的視圖肯定不會(huì)發(fā)生任何變化,而在Angular中卻讓視圖發(fā)生了變化,那它為什么會(huì)自動(dòng)把視圖更新了呢?這離不開一個(gè)叫做zone.js的庫(kù),簡(jiǎn)單來(lái)說(shuō),它是對(duì)發(fā)生值改變的事件做了一些處理,這個(gè)會(huì)在后面的部分詳細(xì)講解,這里暫時(shí)知道這個(gè)就可以了。

如果我不想讓這個(gè)庫(kù)做這些處理,Angular還為我們提供了禁用zone.js的方法。

可以在main.ts中設(shè)置禁用zone.js。

import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';  import { AppModule } from './app/app.module'; import { environment } from './environments/environment';  if (environment.production) {   enableProdMode(); }  platformBrowserDynamic().bootstrapModule(AppModule, {   ngZone: 'noop' })   .catch(err => console.error(err));
登錄后復(fù)制

淺析Angular變更檢測(cè)中的DOM更新機(jī)制

當(dāng)我們禁用zone.js,視圖并未發(fā)生更新。到源碼里找一下視圖更新的相關(guān)代碼。

 */ class ApplicationRef {     /** @internal */     constructor(_zone, _injector, _exceptionHandler, _initStatus) {         this._zone = _zone;         this._injector = _injector;         this._exceptionHandler = _exceptionHandler;         this._initStatus = _initStatus;         /** @internal */         this._bootstrapListeners = [];         this._views = [];         this._runningTick = false;         this._stable = true;         this._destroyed = false;         this._destroyListeners = [];         /**          * Get a list of component types registered to this application.          * This list is populated even before the component is created.          */         this.componentTypes = [];         /**          * Get a list of components registered to this application.          */         this.components = [];         this._onMicrotaskEmptySubscription = this._zone.onMicrotaskEmpty.subscribe({             next: () => {                 this._zone.run(() => {                     this.tick();                 });             }         });         ...     }  /**      * Invoke this method to explicitly process change detection and its side-effects.      *      * In development mode, `tick()` also performs a second change detection cycle to ensure that no      * further changes are detected. If additional changes are picked up during this second cycle,      * bindings in the app have side-effects that cannot be resolved in a single change detection      * pass.      * In this case, Angular throws an error, since an Angular application can only have one change      * detection pass during which all change detection must complete.      */     tick() {         NG_DEV_MODE && this.warnIfDestroyed();         if (this._runningTick) {             const errorMessage = (typeof ngDevMode === 'undefined' || ngDevMode) ?                 'ApplicationRef.tick is called recursively' :                 '';             throw new RuntimeError(101 /* RuntimeErrorCode.RECURSIVE_APPLICATION_REF_TICK */, errorMessage);         }         try {             this._runningTick = true;             for (let view of this._views) {                 view.detectChanges();             }             if (typeof ngDevMode === 'undefined' || ngDevMode) {                 for (let view of this._views) {                     view.checkNoChanges();                 }             }         }         catch (e) {             // Attention: Don't rethrow as it could cancel subscriptions to Observables!             this._zone.runOutsideAngular(() => this._exceptionHandler.handleError(e));         }         finally {             this._runningTick = false;         }     }  }
登錄后復(fù)制

大致解讀一下,這個(gè)ApplicationRef是Angular整個(gè)應(yīng)用的實(shí)例,在構(gòu)造函數(shù)中,zone(zone庫(kù))的onMicrotaskEmpty(從名字上看是一個(gè)清空微任務(wù)的一個(gè)subject)訂閱了一下。在訂閱里,調(diào)用了tick(),那tick里做了什么呢

思考: 上次說(shuō)了最好訂閱不要放到constructor里去訂閱,這里怎么這么不規(guī)范呢?

當(dāng)然不是,上次我們說(shuō)的是Angular組件里哪些應(yīng)該放constructor,哪些應(yīng)該放ngOnInit里的情況。但這里,ApplicationRef人家是一個(gè)service呀,只能將初始化的代碼放constructor

在tick函數(shù)里,如果發(fā)現(xiàn)這個(gè)tick函數(shù)正在執(zhí)行,則會(huì)拋出異常,因?yàn)檫@個(gè)是整個(gè)應(yīng)用的實(shí)例,不能遞歸調(diào)用。然后,遍歷了所有個(gè)views,然后每個(gè)view都執(zhí)行了detectChanges(),也就是執(zhí)行了下變更檢測(cè),什么是變更檢測(cè),會(huì)在后面詳細(xì)講解。緊接著,如果是devMode,再次遍歷所有的views,每個(gè)view執(zhí)行了checkNoChanges(),檢查一下有沒(méi)有變化,有變化則會(huì)拋錯(cuò)(后面會(huì)詳細(xì)說(shuō)這個(gè)問(wèn)題,暫時(shí)跳過(guò))。

那好了,現(xiàn)在也知道怎么能讓它更新了,就是要調(diào)用一下ApplicationReftick方法。

import { Component, ViewChild, ElementRef, ApplicationRef } from '@angular/core'; @Component({   selector: 'app-root',   templateUrl: './app.component.html',   styleUrls: ['./app.component.scss'] }) export class AppComponent  {   name = 'Empty';    @ViewChild('textContainer') textContainer: ElementRef = {} as any;    constructor(private app: ApplicationRef){}    normalClick(): void {     this.name = 'Hello Angular';      console.log(this.textContainer.nativeElement.innerText);      this.app.tick();   } }
登錄后復(fù)制

果然,可以正常的更新視圖了。

我們來(lái)簡(jiǎn)單梳理一下,DOM的更新依賴于tick() 的觸發(fā),zone.js幫助開發(fā)者無(wú)需手動(dòng)觸發(fā)這個(gè)操作。好了,現(xiàn)在可以把zone.js啟用了。

那什么是變更檢測(cè)呢?繼續(xù)期待下一篇哦。

贊(0)
分享到: 更多 (0)
?
網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)
午夜无码无遮挡在线视频| 伊人精品无码AV一区二区三区 | 欧美成人一区二区三区不卡| 亚洲AV成人无码网站大全| JAVAPARSER少妇高潮| 好大好湿好硬顶到了好爽视频| 人人妻人人澡人人爽欧美二区| 亚洲欧美精品水蜜桃| 国产AⅤ精品一区二区三区久久| 迷迷糊糊挺进岳身体| 亚洲AV片在线观看| 成人性生交大片免费看好| 久久午夜私人影院| 性欧美暴力猛交69HD| 成人免费无遮挡在线播放| 麻豆XXXXXX在线观看| 亚洲AV无码一区二区三区电影| 成人熟女视频一区二区三区| 美女把尿口扒开让男人桶爽| 亚洲AV永久无码精品秋霞电影秋| 吃瓜黑料视频永久地址| 免费无码又爽又刺激高潮的漫画| 亚洲丰满熟妇在线播放电影全集| 国产97色在线 | 日| 欧美人与动交视频播放| 亚洲中文字幕无码久久2020| 国产网红无码精品视频| 搡BBB搡BBBB搡BBBB| 99精品国产福利在线观看| 久久AⅤ人妻少妇嫩草影院| 无遮挡国产高潮视频免费观看| 超鹏97国语在线| 欧美 日韩 国产 亚洲 色| 亚洲中文字幕日产乱码小说 | HEYZO无码综合国产精品| 久久久久久久99精品免费观看| 性色AV免费观看| 国产AⅤ激情无码久久男男剧| 奇米综合四色77777久久| 中文字幕免费不卡二区| 久久精品国产久精国产思思| 学生无码AV一区二区三区| 国产成人无码AV一区二区在线观| 人人人爽人人澡人人高潮| 99热门精品一区二区三区无码| 久久精品中文字幕有码| 亚洲国产成人精品青青草原导航| 国产精品亚洲片在线| 睡着了强行挺进岳身体| 啊灬啊灬啊灬快灬深高潮了亚洲乱色视频在线观看 | WWW久久无码天堂MV| 内射人妻视频国内| 真人做受试看120分钟小视频| 精品无码久久久久久久久久| 亚洲AV日韩AV无码污污网站| 国产精品亚洲专区无码蜜芽| 偷朋友人妻系列H文| 国产A∨精品一区二区三区不卡 | 无遮挡无码H纯肉动漫在线观看| 丰满人妻跪趴高撅肥臀| 入禽太深免费视频| 村长你的机巴太粗太长了| 日韩国产成人精品视频| 别揉我奶头~嗯~啊~免费视频| 欧洲成人午夜精品无码区久久| 99国精产品灬源码168| 内射人妻无码色AV天堂| 97久久综合亚洲色HEZYO| 欧美A片XⅩX黑人性受| 7777久久亚洲中文字幕蜜桃| 精品人妻无码中字系列| 香蕉久久夜色精品国产| 天天摸日日摸狠狠添高潮喷| 俄罗斯ZOOM与人性ZOOM| 少妇夜夜爽夜夜春夜夜高潮| 国产A在亚洲线播放| 调教小奴高潮惩罚PLAY道具| 国产成人综合亚洲AV| 无码少妇一区二区三区芒果| 国产日产欧产精品精品蜜芽| 亚洲AV乱码一区二区三区在线观看 | 久久久久精品国产亚洲AV蜜桃| 亚洲综合成人AⅤ在线网站| 久久夜色精品国产网站| 中文字幕天天躁日日躁狠狠躁免费| 男人GAY自慰吞精网站| FREESEXVIDEOS性亚| 日本人も中国人も汉字を| 丰满少妇发泄14P| 午夜阳光精品一区二区三区| 好男人好资源在线影视官网 | 性欧美玩弄性少妇HD| 欧美老熟妇性BBBBBXXXX| 边做饭边被躁BD苍井空小说| 私はあなたのおさんです怎么读 | 精品久久久无码中文字幕天天 | 麻豆果冻传媒2021精品传媒一| 18级成人毛片免费观看| 人人澡人摸人人添| 国产精品 高清 尿 小便 嘘嘘 | 精品国产乱码久久久久久人妻| 一区国产情侣宾馆射| 欧美成人免费全部网站| 成熟丰满的人妻中文字幕电影| 无码国产精品一区二区免费式影视| 国产又爽又黄又舒服又刺激视频| 亚洲色大成网站WWW永久网站| 男女24式动态图| 成人爽A毛片免费| 亚洲AV成人无码影视网| 久久久久亚洲精品无码网址蜜桃| 7777色情ⅩXXX欧美色妇| 色窝窝无码一区二区三区成人网站 | 国产精品久久久久久久久久直播| 亚洲AV永久无码精品秋霞电影影 | 国产精品视频第一区二区三区| 亚洲国产精品无码一线岛国 | 我把英语课代表按在桌子上抄 | 欧洲精品不卡1卡2卡三卡| 公翁的粗大放进我的秘密电影| 亚洲AV永久无码精品无码一区二区| 久久天天躁狠狠躁夜夜AV不卡| FREE性满足HD| 无遮挡又黄又刺激又爽的视频| 久久大香香蕉国产拍国| AV无码专区亚洲AVL在线观看| 十八禁羞羞爽爽爽爱爱午夜网| 狠狠色噜噜狠狠狠777米奇| 中文无码制服丝袜人妻AV| 日韩精品久久久肉伦网站| 国色天香在线视频免费观看 | 特级AAAAAAAAA毛片免费| 精品美女AⅤ国产女教师蜜臀| 18禁美女黄网站色大片免费观看| 色综合久久蜜芽国产精品 | 亚洲伊人精品无码一区二区 | 国产亚洲欧美精品一区| 中国大陆高清AⅤ毛片| 少妇伦子伦情品无吗| 久久AV无码精品人妻系列果冻| www.成人av| 亚洲AV无码一区二区三区天堂古| 母亲とが话していま在线观看| 国产AV无码区亚洲AV欧美| 野花免费高清完整在线观看| 日日碰狠狠添天天爽超碰97| 久久99精品久久久久久久清纯 | 久久国产热这里只有精品| 帮妺妺洗澡忍不住C了她作文| 亚洲AV色区一区二区三区| 欧美精品VIDEOSEX极品| 国产凸凹视频一区二区| 99国产精品99久久久久久| 无人区码一码二码三码| 免费人成视在线观看不卡| 国产精品亚洲成在人线| 337P日本欧洲亚洲大胆裸体艺| 无码人妻精品中文字幕不卡| 免费无码又爽又刺激聊天APP | 国产精品久久久久精品香蕉| 中文字幕AV无码免费一区| 无码秘 蜜桃一区二区三区 | 狠狠做五月深爱婷婷| 凹凸国产熟女精品视频国语| 亚洲精品无码永久中文字幕| 日本高清无卡码一区二区| 久久精品无码一区二区APP| 公交车上掀开麻麻超短裙| 在办公室里揉弄小雪好爽| 无码人妻黑人中文字幕| 欧美裸体XXXX| 精品久久久久中文字幕日本| 绯色av一区二区| 中年人妻丰满AV无码久久不卡| 午夜AV内射一区二区三区红桃视| 欧美乱子YELLOWVIDEO| 精品亚洲韩国一区二区三区| 公交车被CAO得合不拢腿视频| 中文人妻无码一区二区三区在线 | 蜜中蜜3在线观看视频| 国产一精品一AV一免费爽爽| 办公室被公司领导C了很多次| 亚洲一区二区三区小说| 无码国产成人午夜在线观看 | 欧美性爱一二三区| 久久精品国产精品亚洲蜜月| 国产精品R级最新在线观看| H国产小视频福利免费视频| 亚洲尤码不卡AV麻豆| 无人区乱码一区二区三区| 人善交VIDEOS欧美3D| 美女扒开腿让男人桶爽揉| 黑人上司粗大拔不出来电影| 疯狂做受XXXX高潮视频免费| 91久人人做人人妻人人玩精品| 亚洲成AV人片天堂网久久| 天天看片在线完整版| 日本适合十八岁以上的护肤品| 妺妺窝人体色www聚色窝仙踪| 精品无码一区二区三区|