面试题-angular

angular数据绑定原理

Angular 根据数据流的方向提供三种类型的数据绑定:
  • 从数据源到视图-- 插值/属性绑定
  • 从视图到数据源--事件绑定
  • 双向,从视图到数据源再到视图

 

angular的数据绑定有单向绑定和双向绑定
单向绑定包括属性绑定,差值绑定,事件绑定
双向绑定将属性绑定与事件绑定结合在一起
属性绑定设置特定的元素属性,事件绑定侦听元素更改事件

双向绑定使视图与数据模型同步修改
数据绑定处理的是dom元素property属性和元素事件
angular拓展了html也就是模板,可以使用angular的诸多语法。
当组件类的属性发生更改(数据模型更改),angular会自动更新已渲染的dom。这部分操作dom的工作由框架负责。
当用户操作触发事件,如按键,鼠标事件(视图更改),angular为目标事件配置事件处理函数,将事件对象$event传给处理事件的方法,通过这个事件对象更改组件类的属性
这样就完成了视图与数据模型的同步修改

例如:

双向绑定也为应用中的组件提供了一种共享数据的方式。

使用双向绑定绑定来侦听事件并在父组件和子组件之间同步更新值。

在子组件中设置输入@input输出@output,当子组件数据发生更改时,通过eventemitter发送出去。使用双向绑定的话,值就同步更新了,就不需要再写事件绑定去接受子组件传过来的值了

表单元素使用angular formModule提供的ngModel轻松实现双向绑定

 

视图与数据模型同步修改--编写数据绑定时,你只是在处理 DOM Property 和目标对象的事件

<input [value]="name" (input)="name = $event.target.value" />
--数据到视图(通过js更改name属性的值)
当浏览器渲染 <input> 时,它将创建一个具有 value 这个 Property 的相应 DOM 节点,并将其 value 初始化为 name属性的值。
当数据改变--最终通过操纵 DOM API 来更新视图元素,这部分操纵 DOM 的工作,由框架来负责
 Angular 使用额外的语法扩展了 HTML,使你可以从组件中插入动态值。当组件的状态更改时,Angular 会自动更新已渲染的 DOM
 
--视图到数据(用户输入,点击等)
当用户将 Sally 输入到 <input> 时,DOM 元素的 value Property 会变为 Sally
  • 该代码绑定到 <input> 元素的 input 事件,该事件允许代码监听这些更改。
  • 当用户做出更改时,该组件会引发 input 事件。
  • 这个绑定会在一个上下文中执行该语句,此上下文中包含 DOM 事件对象 $event。
  • Angular 会通过调用input 事件来获取更改后的文本,并用它更新 name 属性

模板上[]的语法代表了输入,html元素或组件通过这种语法接收输入值。
模板上()的语法代表了输出,html元素通过事件或者组件通过EventEmitter向外输出值。

单向绑定

属性(property)绑定:在单一方向上将值从组件的属性送到目标元素的属性。
<img [src]="itemImageUrl">   Property 绑定 (src是property)

<tr><td [colSpan]="1 + 1">Three-Four</td></tr>   Property 绑定(推荐)

<tr><td [attr.colspan]="1 + 1">One-Two</td></tr>    

<button [attr.aria-label]="actionName">{{actionName}} with Aria</button>    Attribute 绑定(没有可绑定的元素 Property时,如ARIASVG

插值和 Property 绑定只能设置 Property,不能设置 Attribute

插值绑定:将在相应的组件模板中显示变量的值。
通过插值,你可以动态更改应用视图中显示的内容,使用双花括号{{}}作为定界符
<h3>Currentcustomer:{{currentCustomer}}</h3>

事件绑定:用户操作触发DOM事件,可以侦听并响应用户操作,例如按键、鼠标移动、点击和触摸
<button(click)="onSave()">Save</button>

在事件绑定中,Angular 会为目标事件配置事件处理函数。

当组件或指令引发事件时,处理程序就会执行模板语句。模板语句会执行一个动作来响应这个事件。

处理事件的常见方法之一是把事件对象 $event 传给处理该事件的方法。$event 对象通常包含该方法所需的信息

双向绑定(属性绑定+事件绑定)

双向绑定为应用中的组件提供了一种共享数据的方式。
使用双向绑定绑定来侦听事件并在父组件和子组件之间同步更新值。

Angular的双向绑定语法是方括号和圆括号的组合,[]进行属性绑定,()进行事件绑定

为了使双向数据绑定有效,@Output() 属性的名字必须遵循 inputChange 模式,其中 input 是相应 @Input() 属性的名字。
例如,如果 @Input() 属性为 size ,则 @Output() 属性必须为 sizeChange
 

forRoot()方法是什么?

静态方法 forRoot() 是一个约定,可以更轻松的配置模块的想要单例使用的服务及其提供者
RouterModule.forRoot() 就是一个很好的例子。应用把一个 Routes 对象传给 RouterModule.forRoot(),为的就是使用路由配置全应用级的 Router 服务。
RouterModule.forRoot() 返回一个ModuleWithProviders对象。 你把这个结果添加到根模块 AppModule 的 imports 列表中。
只能在应用的根模块 AppModule 中调用并导入 forRoot() 的结果。 在其它模块,特别是惰性加载模块中,不要导入它。
 
通常,你只需要用 providedIn 提供服务,用 forRoot()/forChild() 提供路由即可
如果模块同时定义了 providers(服务)和 declarations(组件、指令、管道),那么,当你同时在多个特性模块中加载此模块时,这些服务就会被注册在多个地方。
这会导致出现多个服务实例,并且该服务的行为不再像单例一样。

有多种方式来防止这种现象:
用 providedIn 语法代替在模块中注册服务的方式。
把你的服务分离到它们自己的模块中。
在模块中分别定义 forRoot() 和 forChild() 方法
 

angular服务

服务是指那些能够被其它的组件或者指令调用的单一的,可共享的代码块.服务能够使我们提高代码的利用率,方便组件之间共享数据和方法
 
 

angular变更检测

为什么需要变更检测?

在还是 jQuery 的时代,当在 js 中改变了某个变量的数据,而这个变量是需要在 Html 中显示出来的。

我们的做法是通过 DOM 先获取到显示该变量的视图元素,然后借助 DOM API 来更新这个视图元素,这是原始的方式。

三大框架最终其实也都还是要通过操纵 DOM API 来更新视图元素

与原始方式的区别就是,这部分操纵 DOM 的工作,由框架来负责

实现的关键点就在于,如何知道,我们对数据进行了更新?---就需要变更检测了

更改任何模型时, Angular会检测到更改并立即更新视图。这是Angular中的更改检测。该机制的目的是确保基础视图始终与其对应的模型保持同步。

怎么实现?

angular的变更检测机制是由zone.js 来实现的,Angular 使用NgZone获取变化的通知,然后进行全面的变化检测,进而更新Dom

  • Events:click,mouseover,mouseout,keyup,keydown 等所有的浏览器事件
  • Timer:setTimeout,setInterval
  • XHR:异步请求
 
当angular应用运行时,每个组件都会生成一个属于组件自己的变更检测器
当检测到变化,zone.js就会根据组件的变更检测策略,以判断组件是否需要更新模板

angular实现了2个变更检测策略

默认情况下(ChangeDetectionStrategy.Default),父组件的变更检测发生时,子组件也会触发变更检测。
当变更检测运行时,会处理组件模板上的所有绑定关系,如果一个组件的属性改变,与其绑定的模板的相应区域也随之改变
一个angular应用是一颗组件树,每个组件都有一个视图与之相关联。当 Angular 进行变化检测时,这棵树中的每一个组件都会被检测。
某个组件声明自己的变更策略为onpush,只有当这个组件的输入属性发生变化,zone.js才会检测当前组件及其子组件
 
 

脏检查的过程

Angular的数据流是自顶而下,从父组件到子组件单项流动,单项数据流保证了高效可预测的变化检测。尽管检查了父组件之后,子组件可能会改变父组件的数据使得父组件需要再次被检查,这是不被推荐的数据处理方式。在开发模式下Angular会进行二次检查,如果出现上述情况,二次检查就会报错:Expression Changed After It Has Been Checked Error。而在生产环境中,脏检查只会执行一次。

检测顺序 Detection Sequence

更新所有子组件的绑定属性

调用所有子组件的 OnChanges,OnInit,DoCheck,AfterContentInit 生命周期钩子

更新当前组件的 DOM

子组件触发变更检测

调用所有子组件的的 AfterViewInit 的生命周期钩子

 

Angular 性能优化

知名的 Angular 开源组件库 ng-zorro 就使用了大量的 OnPush 策略

angular与react对比

框架与库

React 是一个用于构建用户界面的 JavaScript 库

React不是一个真正的框架,它是一个库。依赖第三方库

比如 客户端-服务器通信 要使用其他库Axios ,是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

比如 react-redus-状态管理

Angular 是一个应用设计框架与开发平台,用于创建高效、复杂、精致的单页面应用。

  • 一个基于 TypeScript 的框架,

  • 一组完美集成的库,涵盖各种功能,包括路由、表单管理、客户端-服务器通信,rxjs等

  • 一套开发工具,可帮助你开发、构建、测试和更新代码

基于组件的体系结构:使用这两种工具的可重用和可维护组件 

这两个框架都有基于组件的体系结构,比其他体系结构更容易维护

TypeScript与JavaScript和JSX的比较

Angular使用TypeScript语言。适合大型项目的。有类型检查

React使用JavaScriptES6+和JSX脚本。(需要设置一下才能使用ts)

JSX(增强的html)是JavaScript的语法扩展,用于简化UI编码,使JavaScript代码看起来像HTML。

DOM:真实与虚拟

React使用虚拟DOM,而Angular操作真实DOM,并使用更改检测来查找哪些组件需要更新。

单向数据流与双向数据绑定

angular使用双向数据绑定,视图与数据模型是同步更改的(andular变更检测)

react是单项数据流,从父组件流向子组件,使用虚拟dom (react更新视图的思想是:只要state变化就重新渲染视图)

使用场景

angular 多用于开发大型的,单页应用
react 灵活使用第三方库  跨平台应用程序开发
posted @ 2022-03-18 17:04  litiyi  阅读(126)  评论(0编辑  收藏  举报