<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        [譯]Angular屬性綁定更新機制-Laravel/Angular技術分享

        來源:懂視網 責編:小采 時間:2020-11-27 19:31:35
        文檔

        [譯]Angular屬性綁定更新機制-Laravel/Angular技術分享

        [譯]Angular屬性綁定更新機制-Laravel/Angular技術分享:本篇文章主要的講述了關于angularjs屬性綁定更新機制,還有angularjs更新屬性的詳解,都在這篇文章中,現在就讓我們一起來看這篇文章吧angularjs屬性綁定更新機制解釋:所有現代前端框架都是用組件來合成 UI,這樣很自然就會產生父子組件層級,這就需要框架提
        推薦度:
        導讀[譯]Angular屬性綁定更新機制-Laravel/Angular技術分享:本篇文章主要的講述了關于angularjs屬性綁定更新機制,還有angularjs更新屬性的詳解,都在這篇文章中,現在就讓我們一起來看這篇文章吧angularjs屬性綁定更新機制解釋:所有現代前端框架都是用組件來合成 UI,這樣很自然就會產生父子組件層級,這就需要框架提

        angularjs屬性綁定更新機制解釋:

        所有現代前端框架都是用組件來合成 UI,這樣很自然就會產生父子組件層級,這就需要框架提供父子組件通信的機制。同樣,Angular 也提供了兩種方式來實現父子組件通信:輸入輸出綁定和共享服務。對于 stateless presentational components 我更喜歡輸入輸出綁定方式,然而對于 stateful container components 我使用共享服務方式。

        本文主要介紹輸入輸出綁定方式,特別是當父組件輸入綁定值變化時,Angular 如何更新子組件輸入值。如果想了解 Angular 如何更新當前組件 DOM,可以查看 譯 Angular DOM 更新機制,這篇文章也會有助于加深對本文的理解。由于我們將探索 Angular 如何更新 DOM 元素和組件的輸入綁定屬性,所以假定你知道 Angular 內部是如何表現組件和指令的,如果你不是很了解并且很感興趣,可以查看 譯 為何 Angular 內部沒有發現組件, 這篇文章主要講了 Angular 內部如何使用指令形式來表示組件。而本文對于組件和指令兩個概念互換使用,因為 Angular 內部就是把組件當做指令。

        模板綁定語法

        你可能知道 Angular 提供了 屬性綁定語法 —— [],這個語法很通用,它可以用在子組件上,也可以用在原生 DOM 元素上。如果你想從父組件把數據傳給子組件 b-comp 或者原生 DOM 元素 span,你可以在父組件模板中這么寫:

        import { Component } from '@angular/core';
        
        @Component({
         moduleId: module.id,
         selector: 'a-comp',
         template: `
         <b-comp [textContent]="AText"></b-comp>
         <span [textContent]="AText"></span>
         `
        })
        export class AComponent {
         AText = 'some';
        }

        你不必為原生 DOM 元素做些額外的工作,但是對于子組件 b-comp 你需要申明輸入屬性 textContent

        @Component({
         selector: 'b-comp',
         template: 'Comes from parent: {{textContent}}'
        })
        export class BComponent {
         @Input() textContent;
        }

        這樣當父組件 AComponent.AText 屬性改變時,Angular 會自動更新子組件 BComponent.textContent 屬性,和原生元素 span.textContent 屬性。同時,還會調用子組件 BComponent 的生命周期鉤子函數 ngOnChanges(注:實際上還有 ngDoCheck,見下文)。

        你可能好奇 Angular 是怎么知道 BComponentspan 支持 textContent 綁定的。這是因為 Angular 編譯器在解析模板時,如果遇到簡單 DOM 元素如 span,就去查找這個元素是否定義在 dom_element_schema_registry,從而知道它是 HTMLElement 子類,textContent 是其中的一個屬性(注:可以試試如果 span 綁定一個 [abc]=AText 就報錯,沒法識別 abc 屬性);如果遇到了組件或指令,就去查看其裝飾器 @Component/@Directive 的元數據 input 屬性里是否有該綁定屬性項,如果沒有,編譯器同樣會拋出錯誤:

        Can’t bind to ‘textContent’ since it isn’t a known property of …

        這些知識都很好理解,現在讓我們進一步看看其內部發生了什么。

        組件工廠

        盡管在子組件 BComponentspan 元素綁定了輸入屬性,但是輸入綁定更新所需要的信息全部在父組件 AComponent 的組件工廠里。讓我們看下 AComponent 的組件工廠代碼:

        function View_AComponent_0(_l) {
         return jit_viewDef1(0, [
         jit_elementDef_2(..., 'b-comp', ...),
         jit_directiveDef_5(..., jit_BComponent6, [], {
         textContent: [0, 'textContent']
         }, ...),
         jit_elementDef_2(..., 'span', [], [[8, 'textContent', 0]], ...)
         ], function (_ck, _v) {
         var _co = _v.component;
         var currVal_0 = _co.AText;
         var currVal_1 = 'd';
         _ck(_v, 1, 0, currVal_0, currVal_1);
         }, function (_ck, _v) {
         var _co = _v.component;
         var currVal_2 = _co.AText;
         _ck(_v, 2, 0, currVal_2);
         });
        }

        如果你讀了 譯 Angular DOM 更新機制 或 譯 為何 Angular 內部沒有發現組件,就會對上面代碼中的各個視圖節點比較熟悉了。前兩個節點中,jit_elementDef_2 是元素節點,jit_directiveDef_5 是指令節點,這兩個組成了子組件 BComponent;第三個節點 jit_elementDef_2 也是元素節點,組成了 span 元素。(想看更多就到PHP中文網AngularJS開發手冊中學習)

        節點綁定

        相同類型的節點使用相同的節點定義函數,但區別是接收的參數不同,比如 jit_directiveDef_5 節點定義函數參數如下:

        jit_directiveDef_5(..., jit_BComponent6, [], {
         textContent: [0, 'textContent']
        }, ...),

        其中,參數 {textContent: [0, 'textContent']} 叫做 props,這點可以查看 directiveDef 函數的參數列表:

        directiveDef(..., props?: {[name: string]: [number, string]}, ...)

        props 參數是一個對象,每一個鍵為綁定屬性名,對應的值為綁定索引和綁定屬性名組成的數組,比如本例中只有一個綁定,textContent 對應的值為:

        {textContent: [0, 'textContent']}

        如果指令有多個綁定,比如:

        <b-comp [textContent]="AText" [otherProp]="AProp">

        props 參數值也包含兩個屬性:

        jit_directiveDef5(49152, null, 0, jit_BComponent6, [], {
         textContent: [0, 'textContent'],
         otherProp: [1, 'otherProp']
        }, null),

        Angular 會使用這些值來生成當前指令節點的 binding,從而生成當前視圖的指令節點。在變更檢測時,每一個 binding 決定 Angular 使用哪種操作來更新節點和提供上下文信息,綁定類型是通過 BindingFlags 設置的(注:每一個綁定定義是 BindingDef,它的屬性 flags: BindingFlags 決定 Angular 該采取什么操作,比如 Class 型綁定和 Style 型綁定都會調用對應的操作函數,見下文)。比如,如果是屬性綁定,編譯器會設置綁定標志位為:

        export const enum BindingFlags {
         TypeProperty = 1 << 3,
        注:上文說完了指令定義函數的參數,下面說說元素定義函數的參數。

        本例中,因為 span 元素有屬性綁定,編譯器會設置綁定參數為 [[8, 'textContent', 0]]

        jit_elementDef2(..., 'span', [], [[8, 'textContent', 0]], ...)

        不同于指令節點,對元素節點來說,綁定參數結構是個二維數組,因為 span 元素只有一個綁定,所以它僅僅只有一個子數組。數組 [8, 'textContent', 0] 中第一個參數也同樣是綁定標志位 BindingFlags,決定 Angular 應該采取什么類型操作(注:[8, 'textContent', 0] 中的 8 表示為 property 型綁定):

        export const enum BindingFlags {
         TypeProperty = 1 << 3, // 8

        其他類型標志位已經在文章 譯 Angular DOM 更新機制 有所解釋:

        TypeElementAttribute = 1 << 0,
        TypeElementClass = 1 << 1,
        TypeElementStyle = 1 << 2,

        編譯器不會為指令定義提供綁定標志位,因為指令的綁定類型也只能是 BindingFlags.TypeProperty

        注:節點綁定 這一節主要講的是對于元素節點來說,每一個節點的 binding 類型是由 BindingFlags 決定的;對于指令節點來說,每一個節點的 binding 類型只能是 BindingFlags.TypeProperty

        updateRenderer 和 updateDirectives

        組件工廠代碼里,編譯器還為我們生成了兩個函數:

        function (_ck, _v) {
         var _co = _v.component;
         var currVal_0 = _co.AText;
         var currVal_1 = _co.AProp;
         _ck(_v, 1, 0, currVal_0, currVal_1);
        },
        function (_ck, _v) {
         var _co = _v.component;
         var currVal_2 = _co.AText;
         _ck(_v, 2, 0, currVal_2);
        }

        如果你讀了 譯 Angular DOM 更新機制,應該對第二個函數即 updateRenderer 有所熟悉。第一個函數叫做 updateDirectives。這兩個函數都是 ViewUpdateFn 類型接口,兩者都是視圖定義的屬性:

        interface ViewDefinition {
         flags: ViewFlags;
         updateDirectives: ViewUpdateFn;
         updateRenderer: ViewUpdateFn;

        有趣的是這兩個函數的函數體基本相同,參數都是 _ck_v,并且兩個函數的對應參數都指向同一個對象,所以為何需要兩個函數?

        因為在變更檢測期間,這是不同階段的兩個不同行為:

      1. 更新子組件的輸入綁定屬性

      2. 更新當前組件的 DOM 元素

      3. 這兩個操作是在變更檢測的不同階段執行,所以 Angular 需要兩個獨立的函數分別在對應的階段調用:

      4. updateDirectives——變更檢測的開始階段被調用,來更新子組件的輸入綁定屬性

      5. updateRenderer——變更檢測的中間階段被調用,來更新當前組件的 DOM 元素

      6. 這兩個函數都會在 Angular 每次的變更檢測時 被調用,并且函數參數也是在這時被傳入的。讓我們看看函數內部做了哪些工作。

        _ck 就是 check 的縮寫,其實就是函數 prodCheckAndUpdateNode,另一個參數就是 組件視圖數據。函數的主要功能就是從組件對象里拿到綁定屬性的當前值,然后和視圖數據對象、視圖節點索引等一起傳入 prodCheckAndUpdateNode 函數。其中,因為 Angular 會更新每一個視圖的 DOM,所以需要傳入當前視圖的索引。如果我們有兩個 span 和兩個組件:

        <b-comp [textContent]="AText"></b-comp>
        <b-comp [textContent]="AText"></b-comp>
        <span [textContent]="AText"></span>
        <span [textContent]="AText"></span>

        編譯器生成的 updateRenderer 函數和 updateDirectives 函數如下:

        function(_ck, _v) {
         var _co = _v.component;
         var currVal_0 = _co.AText;
         
         // update first component
         _ck(_v, 1, 0, currVal_0);
         var currVal_1 = _co.AText;
         
         // update second component
         _ck(_v, 3, 0, currVal_1);
        }, 
        function(_ck, _v) {
         var _co = _v.component;
         var currVal_2 = _co.AText;
         
         // update first span
         _ck(_v, 4, 0, currVal_2);
         var currVal_3 = _co.AText;
        
         // update second span
         _ck(_v, 5, 0, currVal_3);
        }

        沒有什么更復雜的東西,這兩個函數還不是重點,重點是 _ck 函數,接著往下看。

        更新元素的屬性

        從上文我們知道,編譯器生成的 updateRenderer 函數會在每一次變更檢測被調用,用來更新 DOM 元素的屬性,并且其參數 _ck 就是函數 prodCheckAndUpdateNode。對于 DOM 元素的更新,該函數經過一系列的函數調用后,最終會調用函數 checkAndUpdateElementValue,這個函數會檢查綁定標志位是 [attr.name, class.name, style.some] 其中的哪一個,又或者是屬性綁定:

        case BindingFlags.TypeElementAttribute -> setElementAttribute
        case BindingFlags.TypeElementClass -> setElementClass
        case BindingFlags.TypeElementStyle -> setElementStyle
        case BindingFlags.TypeProperty -> setElementProperty;

        上面代碼就是剛剛說的幾個綁定類型,當綁定標志位是 BindingFlags.TypeProperty,會調用函數 setElementProperty,該函數內部也是通過調用 DOM Renderer 的 setProperty 方法來更新 DOM。

        注:setElementProperty 函數里這行代碼 view.renderer.setProperty(renderNode,name, renderValue);,renderer 就是 Renderer2 interface,它僅僅是一個接口,在瀏覽器平臺下,它的實現就是 DefaultDomRenderer2。

        更新指令的屬性

        上文中已經描述了 updateRenderer 函數是用來更新元素的屬性,而 updateDirective 是用來更新子組件的輸入綁定屬性,并且變更檢測期間傳入的參數 _ck 就是函數 prodCheckAndUpdateNode。只是進過一系列函數調用后,最終調用的函數卻是checkAndUpdateDirectiveInline,這是因為這次節點的標志位是 NodeFlags.TypeDirective

        checkAndUpdateDirectiveInline 函數主要功能如下:

        1. 從當前視圖節點里獲取組件/指令對象

        2. 檢查組件/指令對象的綁定屬性值是否發生改變

        3. 如果屬性發生改變:

          a. 如果變更策略設置為 OnPush,設置視圖狀態為 checksEnabled

          b. 更新子組件的綁定屬性值

          c. 準備 SimpleChange 數據和更新視圖的 oldValues 屬性,新值替換舊值

          d. 調用生命周期鉤子 ngOnChanges

        4. 如果該視圖是首次執行變更檢測,則調用生命周期鉤子 ngOnInit

        5. 調用生命周期鉤子 ngDoCheck

        當然,只有在生命周期鉤子在組件內定義了才被調用,Angular 使用 NodeDef 節點標志位來判斷是否有生命周期鉤子,如果查看源碼你會發現類似如下代碼:

        if (... && (def.flags & NodeFlags.OnInit)) {
         directive.ngOnInit();
        }
        if (def.flags & NodeFlags.DoCheck) {
         directive.ngDoCheck();
        }

        和更新元素節點一樣,更新指令時也同樣把上一次的值存儲在視圖數據的屬性 oldValues 里(注:即上面的 3.c 步驟)。

        好了,本篇文章到這就結束了(想看更多就到PHP中文網AngularJS使用手冊中學習),有問題的可以在下方留言提問。

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        [譯]Angular屬性綁定更新機制-Laravel/Angular技術分享

        [譯]Angular屬性綁定更新機制-Laravel/Angular技術分享:本篇文章主要的講述了關于angularjs屬性綁定更新機制,還有angularjs更新屬性的詳解,都在這篇文章中,現在就讓我們一起來看這篇文章吧angularjs屬性綁定更新機制解釋:所有現代前端框架都是用組件來合成 UI,這樣很自然就會產生父子組件層級,這就需要框架提
        推薦度:
        標簽: 綁定 更新 技術
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 国产AV无码专区亚洲AV蜜芽| 亚洲综合国产成人丁香五月激情| 人妻巨大乳hd免费看| 国产精品黄页在线播放免费| 精品亚洲成在人线AV无码| 成人免费视频网站www| 亚洲国产片在线观看| 久久久久久精品免费看SSS| 亚洲国产成人私人影院| 日本视频在线观看永久免费| 亚洲狠狠久久综合一区77777| 久久爰www免费人成| 亚洲男人的天堂在线| 在人线av无码免费高潮喷水| 亚洲人成网亚洲欧洲无码| 狼友av永久网站免费观看| 粉色视频免费入口| 久99精品视频在线观看婷亚洲片国产一区一级在线 | 亚洲精品中文字幕| 免费成人av电影| a级片在线免费看| 亚洲网址在线观看| 在线观看国产情趣免费视频| 色多多A级毛片免费看| 亚洲高清国产AV拍精品青青草原| 99热这里有免费国产精品| 亚洲高清一区二区三区| 四虎影视精品永久免费| 十八禁视频在线观看免费无码无遮挡骂过| 亚洲爆乳精品无码一区二区三区| 久久WWW免费人成一看片| 成人亚洲国产精品久久| 好看的亚洲黄色经典| 无人在线观看完整免费版视频| AV激情亚洲男人的天堂国语| 国产成人精品日本亚洲专区61 | 成年轻人网站色免费看| 免费无毒a网站在线观看| 精品亚洲aⅴ在线观看| 国产一级一片免费播放| 日韩精品无码一区二区三区免费|