Angular refreshView的执行原理

简介: Angular refreshView的执行原理

完整源代码:/**

* Processes a view in update mode. This includes a number of steps in a specific order:

* - executing a template function in update mode;

* - executing hooks;

* - refreshing queries;

* - setting host bindings;

* - refreshing child (embedded and component) views.

*/

function refreshView(tView, lView, templateFn, context) {

   ngDevMode && assertEqual(isCreationMode(lView), false, 'Should be run in update mode');

   const flags = lView[FLAGS];

   if ((flags & 256 /* Destroyed */) === 256 /* Destroyed */)

       return;

   enterView(lView, lView[T_HOST]);

   const checkNoChangesMode = getCheckNoChangesMode();

   try {

       resetPreOrderHookFlags(lView);

       setBindingIndex(tView.bindingStartIndex);

       if (templateFn !== null) {

           executeTemplate(tView, lView, templateFn, 2 /* Update */, context);

       }

       const hooksInitPhaseCompleted = (flags & 3 /* InitPhaseStateMask */) === 3 /* InitPhaseCompleted */;

       // execute pre-order hooks (OnInit, OnChanges, DoCheck)

       // PERF WARNING: do NOT extract this to a separate function without running benchmarks

       if (!checkNoChangesMode) {

           if (hooksInitPhaseCompleted) {

               const preOrderCheckHooks = tView.preOrderCheckHooks;

               if (preOrderCheckHooks !== null) {

                   executeCheckHooks(lView, preOrderCheckHooks, null);

               }

           }

           else {

               const preOrderHooks = tView.preOrderHooks;

               if (preOrderHooks !== null) {

                   executeInitAndCheckHooks(lView, preOrderHooks, 0 /* OnInitHooksToBeRun */, null);

               }

               incrementInitPhaseFlags(lView, 0 /* OnInitHooksToBeRun */);

           }

       }

       // First mark transplanted views that are declared in this lView as needing a refresh at their

       // insertion points. This is needed to avoid the situation where the template is defined in this

       // `LView` but its declaration appears after the insertion component.

       markTransplantedViewsForRefresh(lView);

       refreshEmbeddedViews(lView);

       // Content query results must be refreshed before content hooks are called.

       if (tView.contentQueries !== null) {

           refreshContentQueries(tView, lView);

       }

       // execute content hooks (AfterContentInit, AfterContentChecked)

       // PERF WARNING: do NOT extract this to a separate function without running benchmarks

       if (!checkNoChangesMode) {

           if (hooksInitPhaseCompleted) {

               const contentCheckHooks = tView.contentCheckHooks;

               if (contentCheckHooks !== null) {

                   executeCheckHooks(lView, contentCheckHooks);

               }

           }

           else {

               const contentHooks = tView.contentHooks;

               if (contentHooks !== null) {

                   executeInitAndCheckHooks(lView, contentHooks, 1 /* AfterContentInitHooksToBeRun */);

               }

               incrementInitPhaseFlags(lView, 1 /* AfterContentInitHooksToBeRun */);

           }

       }

       setHostBindingsByExecutingExpandoInstructions(tView, lView);

       // Refresh child component views.

       const components = tView.components;

       if (components !== null) {

           refreshChildComponents(lView, components);

       }

       // View queries must execute after refreshing child components because a template in this view

       // could be inserted in a child component. If the view query executes before child component

       // refresh, the template might not yet be inserted.

       const viewQuery = tView.viewQuery;

       if (viewQuery !== null) {

           executeViewQueryFn(2 /* Update */, viewQuery, context);

       }

       // execute view hooks (AfterViewInit, AfterViewChecked)

       // PERF WARNING: do NOT extract this to a separate function without running benchmarks

       if (!checkNoChangesMode) {

           if (hooksInitPhaseCompleted) {

               const viewCheckHooks = tView.viewCheckHooks;

               if (viewCheckHooks !== null) {

                   executeCheckHooks(lView, viewCheckHooks);

               }

           }

           else {

               const viewHooks = tView.viewHooks;

               if (viewHooks !== null) {

                   executeInitAndCheckHooks(lView, viewHooks, 2 /* AfterViewInitHooksToBeRun */);

               }

               incrementInitPhaseFlags(lView, 2 /* AfterViewInitHooksToBeRun */);

           }

       }

       if (tView.firstUpdatePass === true) {

           // We need to make sure that we only flip the flag on successful `refreshView` only

           // Don't do this in `finally` block.

           // If we did this in `finally` block then an exception could block the execution of styling

           // instructions which in turn would be unable to insert themselves into the styling linked

           // list. The result of this would be that if the exception would not be throw on subsequent CD

           // the styling would be unable to process it data and reflect to the DOM.

           tView.firstUpdatePass = false;

       }

       // Do not reset the dirty state when running in check no changes mode. We don't want components

       // to behave differently depending on whether check no changes is enabled or not. For example:

       // Marking an OnPush component as dirty from within the `ngAfterViewInit` hook in order to

       // refresh a `NgClass` binding should work. If we would reset the dirty state in the check

       // no changes cycle, the component would be not be dirty for the next update pass. This would

       // be different in production mode where the component dirty state is not reset.

       if (!checkNoChangesMode) {

           lView[FLAGS] &= ~(64 /* Dirty */ | 8 /* FirstLViewPass */);

       }

       if (lView[FLAGS] & 1024 /* RefreshTransplantedView */) {

           lView[FLAGS] &= ~1024 /* RefreshTransplantedView */;

           updateTransplantedViewCount(lView[PARENT], -1);

       }

   }

   finally {

       leaveView();

   }

}

核心逻辑:


executing a template function in update mode;

executing hooks;

refreshing queries;

setting host bindings;

refreshing child (embedded and component) views.

256代表destroyed模式。

image.pngimage.pngimage.png

目录
相关文章
|
2月前
|
JavaScript 前端开发 编译器
Angular 中的结构指令运行时的工作原理
Angular 中的结构指令运行时的工作原理
|
2月前
|
JavaScript 前端开发 API
vue的双向绑定的原理,和angular的对比
vue的双向绑定的原理,和angular的对比
77 0
|
8月前
|
JSON 搜索推荐 数据格式
Angular SSR 应用中 serverApp-state script 的工作原理介绍
Angular SSR 应用中 serverApp-state script 的工作原理介绍
|
10月前
|
JavaScript
Angular @Inject 注解的实际应用例子和工作原理浅析
Angular @Inject 注解的实际应用例子和工作原理浅析
|
10月前
|
JavaScript 前端开发
Angular @Injectable 注解的工作原理浅析
Angular @Injectable 注解的工作原理浅析
|
10月前
|
JavaScript 前端开发 容器
从编译后的代码,分析 Angular @Injectable 的工作原理
从编译后的代码,分析 Angular @Injectable 的工作原理
|
JavaScript 前端开发 容器
从编译后的代码,分析 Angular @Injectable 的工作原理
从编译后的代码,分析 Angular @Injectable 的工作原理
86 0
|
JavaScript 前端开发
SAP UI5和Angular的函数防抖(Debounce)和函数节流(Throttle)实现原理介绍
这是Jerry 2021年的第 11 篇文章,也是汪子熙公众号总共第 282 篇原创文章。
SAP UI5和Angular的函数防抖(Debounce)和函数节流(Throttle)实现原理介绍
Angular jasmine spied Method toHaveBeenCalled的执行原理
Angular jasmine spied Method toHaveBeenCalled的执行原理
85 0
Angular jasmine spied Method toHaveBeenCalled的执行原理