이 글은 angular에 관한 프론트엔드 면접 질문 13가지를 요약하고 공유합니다. 도움이 필요한 친구들이 모두 참고할 수 있기를 바랍니다.
1.ng-if와 ng-show/hide의 차이점은 무엇인가요?
첫 번째 차이점은 ng-if
는 후속 표현식이 true
인 경우에만 이 dom
노드를 생성한다는 것입니다. ng-show
는 초기에 생성되며 display:block
및 display:none
을 사용하여 표시 및 비표시를 제어합니다. ng-if
在后面表达式为 true
的时候才创建这个 dom
节点,ng-show
是初始时就创建了,用 display:block
和 display:none
来控制显示和不显示。
第二点区别是,ng-if
会(隐式地)产生新作用域,ng-switch
、 ng-include
等会动态创建一块界面的也是如此。
这样会导致,在 ng-if
中用基本变量绑定 ng-model
,并在外层 p
中把此 model
绑定给另一个显示区域,内层改变时,外层不会同步改变,因为此时已经是两个变量了。
<p>{{name}}</p> <div ng-if="true"> <input type="text" ng-model="name"> </div>
相关教程推荐:《angular教程》
ng-show
不存在此问题,因为它不自带一级作用域。
避免这类问题出现的办法是,始终将页面中的元素绑定到对象的属性(data.x)而不是直接绑定到基本变量(x)上。
2,ng-repeat迭代数组的时候,如果数组中有相同值,会有什么问题,如何解决?
会提示 Duplicates in a repeater are not allowed
. 加 track by $index
可解决。当然,也可以 trace by
任何一个普通的值,只要能唯一性标识数组中的每一项即可(建立 dom
和数据之间的关联)。
3,ng-click 中写的表达式,能使用 JS 原生对象上的方法吗?
不止是 ng-click
中的表达式,只要是在页面中,都不能直接调用原生的 JS
方法,因为这些并不存在于与页面对应的 Controller
的 $scope
中。
4、factory、service 和 provider 是什么关系?
factory
:把 service
的方法和数据放在一个对象里,并返回这个对象
service
:通过构造函数方式创建 service
,返回一个实例化对象
provider
:创建一个可通过 config
配置的 service
,$get
中返回的,就是用 factory
创建 service
的内容
从底层实现上来看,service
调用了 factory
,返回其实例;factory 调用了 provider
,返回其 $get
中定义的内容。factory
和 service
功能类似,只不过 factory
是普通 function
,可以返回任何东西(return
的都可以被访问,所以那些私有变量怎么写,你懂的);
service
是构造器,可以不返回(绑定到 this
的都可以被访问);
provider
是加强版 factory
,返回一个可配置的 factory
。
5、angular 中控制器之间如何通信?
1、Service
2、events
,指定绑定的事件
3、使用 $rootScope
4、controller
之间直接使用$parent, $$childHead
等
5、directive
指定属性进行数据绑定
6,angular 的数据绑定采用什么机制?详述原理
使用的脏检查机制,所谓的双向绑定,其实就是从界面的操作能实时反映到数据,数据的变更能实时展现到界面。AngularJS
在$scope
变量中使用脏值检查来实现了数据双向绑定,并且可以通过$scope.$watch
来监听变化触发回调;
angular
中使用的是脏检查机制,在angular
中每次你绑定一些东西到你的UI上时你就会往$watch
队列里插入一条$watch
,当我们的模版加载完毕时,也就是在linking
阶段(Angular
分为compile
阶段和linking
阶段—译者注),Angular
解释器会寻找每个directive
,然后生成每个需要的$watch
ng-if
가 (암시적으로) 새로운 범위, ng-switch
및 ng-include
를 생성한다는 것입니다. 마찬가지입니다. 나중에 인터페이스를 동적으로 생성하기 위해. 🎜🎜이렇게 하면 ng-if
의 기본 변수와 ng-model
이 바인딩되고 외부 레이어 p
에 이 가 바인딩됩니다. >model
은(는) 다른 표시 영역에 바인딩되어 있습니다. 내부 레이어가 변경되면 외부 레이어는 동시에 변경되지 않습니다. 왜냐하면 이때 이미 두 개의 변수가 있기 때문입니다. 🎜<button ng-click="val=val+1">increase 1</button>🎜 권장 관련 튜토리얼: "🎜angular tutorial🎜"🎜🎜
ng-show
에는 1단계 범위가 제공되지 않기 때문에 이 문제가 없습니다. 🎜🎜이런 종류의 문제를 피하는 방법은 항상 페이지의 요소를 기본 변수(x)에 직접 바인딩하기보다는 개체의 속성(data.x)에 바인딩하는 것입니다. 🎜🎜🎜2.ng-repeat가 배열을 반복할 때 배열에 동일한 값이 있으면 어떻게 되며 어떻게 해결합니까? 🎜🎜🎜 중복은 허용되지 않습니다
라는 메시지가 표시됩니다. 문제를 해결하려면 $index로 추적
을 추가하세요. 물론 배열의 각 항목을 고유하게 식별할 수 있는 한(dom
과 데이터 간의 연결 설정) 일반 값을 추적
할 수도 있습니다. 🎜🎜🎜3. ng-click으로 작성한 표현식은 JS 네이티브 객체에서도 메소드를 사용할 수 있나요? 🎜🎜🎜ng-click
의 표현식뿐만 아니라 기본 JS
메서드도 페이지에 있는 한 직접 호출할 수 없습니다. 존재하지 않기 때문입니다. 해당 컨트롤러
의 $scope
페이지에 있습니다. 🎜🎜🎜4. 공장, 서비스, 공급자의 관계는 무엇인가요? 🎜🎜🎜factory
: service
의 메소드와 데이터를 객체에 넣고 이 객체를 반환합니다.🎜🎜service
: 생성자 메소드를 통해 service 및 인스턴스화된 개체 반환 🎜🎜provider
: config
를 통해 구성할 수 있는 service
를 생성합니다. code>$get에 반환된 것은 factory
🎜🎜를 사용하여 생성된 service
의 콘텐츠입니다. 기본 구현 관점에서 보면 service
factory
호출이 호출되고 해당 인스턴스가 반환됩니다. 팩토리는 provider
를 호출하고 해당 $get
에 정의된 콘텐츠가 반환됩니다. factory
는 service
와 유사한 기능을 가지고 있습니다. 단, factory
는 일반 함수
이고 무엇이든 반환할 수 있습니다( return
에 액세스할 수 있으므로 해당 개인 변수를 작성하는 방법을 알 수 있습니다) 🎜🎜service
는 생성자이므로 return할 필요가 없습니다(this
에 바인딩됨). 🎜🎜provider
는 factory
의 향상된 버전으로, 구성 가능한 factory
를 반환합니다. 🎜🎜🎜5. Angular에서 컨트롤러 간 통신은 어떻게 하나요? 🎜🎜🎜1. 서비스
🎜🎜2. 이벤트
, 바인딩된 이벤트를 지정합니다🎜🎜3. $rootScope
🎜🎜4.컨트롤러🎜🎜5 사이에 $parent, $$childHead
등을 사용하세요. 지시문
은 데이터 바인딩🎜🎜🎜6에 대한 속성을 지정합니다. 어떤 메커니즘인가요? 데이터 바인딩에 사용됩니까? 🎜🎜🎜에서 사용하는 더티 검사 메커니즘의 원리를 자세히 설명하세요. 소위 양방향 바인딩은 실제로 인터페이스 작업이 실시간으로 데이터에 반영될 수 있고 데이터의 변경 사항이 반영될 수 있음을 의미합니다. 실시간으로 인터페이스에 표시됩니다. AngularJS
는 $scope
변수의 더티 값 검사를 사용하여 양방향 데이터 바인딩을 구현하고 $scope.$watch
트리거 콜백을 통해 변경 사항을 모니터링할 수 있습니다. ; 🎜🎜angular
는 더티 검사 메커니즘을 사용합니다. angular
에서는 UI에 무언가를 바인딩할 때마다 $watch를 >$watch
대기열에 추가합니다. 템플릿이 로드되면 linking
단계에 있습니다(Angular
는 컴파일
로 나뉩니다. code> 단계 및 linking
단계 - 번역자 참고 사항) Angular
해석기는 각 지시문
을 찾은 다음 필요한 각 $watch를 생성합니다.
. 🎜当浏览器接受到可以被angular context
处理的事件时就会触发digest
循环,这个循环是由两个更小的循环组合起来的,一个是$watch
列表,一个是$evalAsync
列表,而$watch
列表在$digest
循环中被“脏值检查”解析,在digest
将会遍历我们的watch
,然后询问它是否有属性和值的变化,直到$watch
队列都检查过,在检查数据变化的时候,由于并不知道这个事件是对哪些数据进行了更改,以及这个事件有可能造成事件之外的其他任何地方的数据更改,所以必须进行一次大检查,将所有“注册”过的值全部检查一遍,一次检查称为一个周期,每次最少检查两遍,因为第二遍用来确认,前一遍的变动中是否有数据的变动,导致了其他数据的变动,如果第二次有变动的话,会再执行一遍,直到最后两次完全一致,则停止检查(其实就是个(递归(遍历))的过程),考虑到内存的消耗和死循环的风险,脏检查每个周期最多递归执行10遍,如果超过10遍就会抛出一个错误。当$digest
循环结束时,DOM
相应地变化。
在angular
中
ng-click,ng-change,ng-blur..
.就是对各类用户事件的封装
$timeout,$http,$window,$location...
就是对各种JS/API
事件的封装
ng-model
,以及控制器中的数据,就是对值的“注册”
$scope
本质是一个总的事件逻辑的封装容器,同时抽象为数据载体,实质上数据都存在于浏览器堆内存中
$scope.apply() & $scope.digest()
即Angular
中的“数据大检查”的function
所以如果我们使用了非Angular
封装的事件改编数据时,要手动执行一次大检查
由于Angular
这种脏检查的方法效率不高,如果一个页面绑定的view
超过2000个,就可能存在比较明显的性能问题,官方称之为“脏检查”
举个例子
<button ng-click="val=val+1">increase 1</button>
click
时会产生一次更新的操作(至少触发两次 $digest
循环)
按下按钮浏览器接收到一个事件,进入到angular context
$digest
循环开始执行,查询每个 $watch
是否变化
由于监视$scope.val
的 $watch
报告了变化,因此强制再执行一次 $digest
循环 新的 $digest
循环未检测到变化
浏览器拿回控制器,更新 $scope.val
新值对应的 dom
$digest
循环的上限是 10 次(超过 10次后抛出一个异常,防止无限循环)。
7、一个 angular 应用应当如何良好地分层?
目录结构的划分
对于小型项目,可以按照文件类型组织,比如:
css js controllers models services filters templates
但是对于规模较大的项目,最好按业务模块划分,比如:
css modules account controllers models services filters templates disk controllers models services filters templates
modules
下最好再有一个 common
目录来存放公共的东西。
逻辑代码的拆分
作为一个 MVVM
框架,Angular
应用本身就应该按照 模型,视图模型(控制器),视图来划分。
这里逻辑代码的拆分,主要是指尽量让 controller
这一层很薄。提取共用的逻辑到 service
中 (比如后台数据的请求,数据的共享和缓存,基于事件的模块间通信等),提取共用的界面操作到 directive
中(比如将日期选择、分页等封装成组件等),提取共用的格式化操作到 filter
中等等。
在复杂的应用中,也可以为实体建立对应的构造函数,比如硬盘(Disk
)模块,可能有列表、新建、详情这样几个视图,并分别对应的有 controller
,那么可以建一个 Disk
构造函数,里面完成数据的增删改查和验证操作,有跟 Disk
相关的 controller
,就注入 Disk
构造器并生成一个实例,这个实例就具备了增删改查和验证方法。这样既层次分明,又实现了复用(让 controller
层更薄了)。
8、angular 应用常用哪些路由库,各自的区别是什么?
Angular1.x
中常用 ngRoute
和 ui.router
,还有一种为 Angular2
设计的 new router
(面向组件)。后面那个没在实际项目中用过,就不讲了。
无论是 ngRoute
还是 ui.router
,作为框架额外的附加功能,都必须以 模块依赖 的形式被引入。
区别
ngRoute
模块是 Angular
自带的路由模块,而 ui.router
模块是基于 ngRoute
模块开发的第三方模块。
ui.router
是基于 state
(状态)的, ngRoute
是基于 url
的,ui.router
模块具有更强大的功能,主要体现在视图的嵌套方面。
使用 ui.router
能够定义有明确父子关系的路由,并通过 ui-view
指令将子路由模版插入到父路由模板的 82a3d26c8f4a2e3756041f5a82c4d9fb94b3e26ee717c64999d7867364b1b4a3
中去,从而实现视图嵌套。而在 ngRoute
中不能这样定义,如果同时在父子视图中 使用了 a934de6ad8c4c54b22e1e931400cb97894b3e26ee717c64999d7867364b1b4a3
会陷入死循环。
分属不同团队进行开发的 angular
应用,如果要做整合,可能会遇到哪些问题,如何解决?
可能会遇到不同模块之间的冲突。
比如一个团队所有的开发在 moduleA 下进行,另一团队开发的代码在 moduleB 下
angular.module(&#39;myApp.moduleA&#39;, []) .factory(&#39;serviceA&#39;, function(){ ... }) angular.module(&#39;myApp.moduleB&#39;, []) .factory(&#39;serviceA&#39;, function(){ ... }) angular.module(&#39;myApp&#39;, [&#39;myApp.moduleA&#39;, &#39;myApp.moduleB&#39;])
会导致两个 module
下面的 serviceA
发生了覆盖。
貌似在 Angular1.x
中并没有很好的解决办法,所以最好在前期进行统一规划,做好约定,严格按照约定开发,每个开发人员只写特定区块代码。
9、angular 的缺点有哪些?
强约束
导致学习成本较高,对前端不友好。
但遵守 AngularJS
的约定时,生产力会很高,对 Java
程序员友好。
不利于 SEO
因为所有内容都是动态获取并渲染生成的,搜索引擎没法爬取。
一种解决办法是,对于正常用户的访问,服务器响应 AngularJS 应用的内容;对于搜索引擎的访问,则响应专门针对 SEO 的HTML页面。
性能问题
作为 MVVM 框架,因为实现了数据的双向绑定,对于大数组、复杂对象会存在性能问题。
可以用来 优化 Angular 应用的性能 的办法:
减少监控项(比如对不会变化的数据采用单向绑定)
主动设置索引(指定 track by
,简单类型默认用自身当索引,对象默认使用 $$hashKey
,比如改为 track by item.id
)
降低渲染数据量(比如分页,或者每次取一小部分数据,根据需要再取)
数据扁平化(比如对于树状结构,使用扁平化结构,构建一个 map
和树状数据,对树操作时,由于跟扁平数据同一引用,树状数据变更会同步到原始的扁平数据)
另外,对于Angular1.x ,存在 脏检查 和 模块机制 的问题。
移动端
可尝试 Ionic,但并不完善。
10、解释下什么是$rootScrope
以及和$scope
的区别?
通俗的说$rootScrope
页面所有$scope
的父亲
如何产生$rootScope
和$scope
吧。
step1:Angular解析ng-app
然后在内存中创建$rootScope
。
step2:angular回继续解析,找到{{}}表达式,并解析成变量。
step3:接着会解析带有ng-controller
的p
然后指向到某个controller
函数。这个时候在这个controller
函数变成一个$scope
对象实例。
**11、如何取消 $timeout
, 以及停止一个$watch()
? **
停止 $timeout
我们可以用cancel
:
var customTimeout = $timeout(function () { // your code }, 1000); $timeout.cancel(customTimeout);
停掉一个$watch
:
// .$watch()
会返回一个停止注册的函数
function that we store to a variable var deregisterWatchFn = $rootScope.$watch(‘someGloballyAvailableProperty&#39;, function (newVal) { if (newVal) { // we invoke that deregistration function, to disable the watch deregisterWatchFn(); ... } });
12、Angular Directive中restrict 中分别可以怎样设置?scope中@,=,&有什么区别?
restrict中可以分别设置:
A匹配属性
E匹配标签
C匹配class
M 匹配注释
当然你可以设置多个值比如AEC,进行多个匹配。
在scope中,@,=,&在进行值绑定时分别表示
@
获取一个设置的字符串,它可以自己设置的也可以使用{<!-- -->{yourModel}}
进行绑定的;
=
双向绑定,绑定scope
上的一些属性;
&
用于执行父级scope
上的一些表达式,常见我们设置一些需要执行的函数
13、$apply()
和 $digest()
的区别
안전: $apply()
는 function()
으로 매개변수를 받을 수 있으며, 이 함수
는 try로 래핑됩니다. .. catch
블록을 사용하므로 예외가 발생하면 해당 예외는 $ExceptionHandler 서비스
에 의해 처리됩니다. $apply()
可以接收一个参数作为function()
,这个 function
会被包装到一个 try … catch
块中,所以一旦有异常发生,该异常会被 $exceptionHandler service
处理。
$apply
会使ng
进入 $digest cycle
, 并从$rootScope
开始遍历(深度优先)检查数据变更。
$digest
仅会检查该scope和它的子scope
,当你确定当前操作仅影响它们时,用$digest
$apply
는 ng
가 $digest Cycle
를 입력하고 $rootScope
(깊이 우선)에서 탐색을 시작하도록 합니다. 데이터 변경 사항을 확인하세요. $digest
는 범위와 그 하위 scope
만 확인합니다. 현재 작업이 해당 범위에만 영향을 준다고 확신하는 경우 $digest
를 사용하세요. 성능을 약간 향상시킵니다.
위 내용은 Angle에 관한 13가지 프론트엔드 인터뷰 질문(요약)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!