
使用 Angular開發(fā),可以極大地提升開發(fā)效率。然而,它的性能問題一直被詬病,使它不得不重新設(shè)計架構(gòu),從 Angular2.0到 Angular4.0再到2017年剛剛發(fā)布的 Angular5.0,讓開發(fā)者再一次看到了 Angular的未來,一個著眼于未來的企業(yè)級框架。
然而,回到現(xiàn)實中, Angular1.0版本卻依舊有著無可替代的市場占有率,因此,關(guān)于 Angular1.0中的作用域、數(shù)據(jù)雙向綁定的實現(xiàn)、數(shù)據(jù)丟失、自定義過濾器、自定義指令、自定義服務(wù)、路由等核心技術(shù)依舊是開發(fā)者需要掌握的重點內(nèi)容。1、ng-if與ng-show/hide的區(qū)別有哪些?第一個區(qū)別是,ng-if在后面表達(dá)式為true時才創(chuàng)建DOM節(jié)點,ng-show則在初始時就創(chuàng)建了,可以通過切換ng-hide類控制元素的顯示或隱藏。第二個區(qū)別是,ng-if會(隱式地)產(chǎn)生新作用域。這樣在ng-if中通過ng- model綁定的數(shù)據(jù)改變時,不會影響外面元素中插入的數(shù)據(jù)。下列代碼說明ng-if指令內(nèi)外的name屬性變量已經(jīng)是兩個變量了。<p>{ { name } }</p><div ng-if="true"><nput type="text" ng-model="name"></div>
ng-show不存在此問題。而避免這類問題出現(xiàn)的辦法是,始終為頁面中的元素綁定對象的屬性( data.msg),而不是直接綁定到基本變量(msg)上。<p>{ { data.msg } }</p><div ng-if="true"><input type="text" ng-model="data.msg"></div>
2、當(dāng)使用 ng -repeat指令迭代數(shù)組時,如果數(shù)組中有相同值,會有什么問題?如何解決?會提示 Duplicates in a repeater are not allowed,通過加 track by $index表達(dá)式可解決。當(dāng)然,也可以通過 track by跟蹤任何一個普通的值,只要能唯一地標(biāo)識數(shù)組中的每一項即可(建立DOM和數(shù)據(jù)之間的關(guān)聯(lián))<div ng-repeat="item in arr track by $index"> { {item } }</div>3、ng-cick中寫的表達(dá)式,能使用 JavaScript原生對象上的方法嗎?不只是ng-click中的表達(dá)式,只要是在頁面中,都不能直接調(diào)用原生的 JavaScript方法,因為這些并不存在于與頁面對應(yīng)的 Controller的 $scope中。舉個例子,執(zhí)行以下代碼會發(fā)現(xiàn),什么也沒有顯示。<div>{ { parseInt(100.5)} }</div>
但如果在$scope中定義了以下 parseInt函數(shù),就沒有問題了。$scope. parseInt =function(num){ return parseInt(num)}
對于這種需求,使用一個 filter是不錯的選擇。<div> { {12.34 | icktParseInt)</div>.filter('icktParseInt', function() { return function(value){ return parseInt(value)} } )
filter表示格式化數(shù)據(jù),接受一個輸入,按某規(guī)則處理,返回處理結(jié)果。內(nèi)置 filter有以下9種。<div> { { time | date : 'yyyy-MM-dd' }}</div>
.controller('main', function($scope, $filter) { console.log($filter('date')(Date. now(),'HH:mm:ss'))
6、factory、 service和 provider是什么關(guān)系?它們都是用來實現(xiàn)自定義服務(wù)的方法。但是定義服務(wù)的方式不同, factory通過return暴露服務(wù)的接口對象。factory(' ickt', function () { return { color: 'red ' }}) service通過this暴露服務(wù)的接口對象.service('ickt', function() {this .color = 'green '})
provider創(chuàng)建一個可通過 config配置的服務(wù),通過$get方法的返回值暴露接口。.provider('ickt', function () {this .$get = function () { return { color:'blue'}}})
從底層實現(xiàn)上來看, service調(diào)用了 factory,返回其實例;factory調(diào)用了 provider,返回其$get中定義的內(nèi)容。factory和 service的功能類似,只不過 factory是普通 function,可以返回任何數(shù)據(jù)。service是構(gòu)造器,不需要返回;provider是加強(qiáng)版 factory,返回一個可配置的 factory。7、Angular的數(shù)據(jù)綁定采用什么機(jī)制?請詳述其原理。雙向數(shù)據(jù)綁定是 Angular的核心機(jī)制之一。當(dāng)視圖中有任何數(shù)據(jù)變化時,會更新到模型,當(dāng)模型中數(shù)據(jù)有變化時,視圖也會同步更新。顯然,這需要一個監(jiān)控。數(shù)據(jù)綁定實現(xiàn)原理是 Angular在 scope模型上設(shè)置了一個監(jiān)聽隊列,用來監(jiān)聽數(shù)據(jù)變化并更新視圖。每次綁定一個東西到視圖上時 Angular就會往$watch隊列里插入條$watch,用來檢測它監(jiān)視的模型里是否有變化的內(nèi)客容。當(dāng)瀏覽器接收到可以被Angular context處理的事件時, $digest循環(huán)就會觸發(fā),遍歷所有的$watch,最后更新DOM。例如,在以下代碼中, click事件會產(chǎn)生一次更新操作(至少觸發(fā)兩次 $digest循環(huán))。<button ng-click="val=val+1">demo</button>
按下上式定義的按鈕,瀏覽器接收到一個事件,進(jìn)入 Angular contexto。$digest循環(huán)開始執(zhí)行,查詢毎個$watch是否變化。由于監(jiān)視 $scope.val的 $watch發(fā)現(xiàn)了變化,因此強(qiáng)制再執(zhí)行一次 $digest循環(huán)。發(fā)現(xiàn)數(shù)據(jù)發(fā)生了變化,瀏覽器更新DOM顯示 $scope.val的新值。$digest循環(huán)的上限是10次(超過10次后拋出一個異常,防止無限循環(huán))。8、對于兩個平級界面模塊a和b,如果a中觸發(fā)一個事件,有哪些方式能讓b知道?詳述原理。這個問題換一種說法就是,如何在平級界面模塊間進(jìn)行通信。有兩種方法種是共用服務(wù),一種是基于事件。在 Angular中,通過 factory可以生成一個單例對象,在需要通信的模塊a和b中注入這個對象即可。第一種是借助父控制器。在子 controller中向父控制器發(fā)射( $emit)一個事件,然后在父控制器中監(jiān)聽($on)事件,再廣播($ broadcast)給其他子控制器,這樣通過事件攜帶的參數(shù),實現(xiàn)了數(shù)據(jù)經(jīng)過父控制器,向同級控制器傳播。第二種是借助 $rootScope。每個 Angular應(yīng)用默認(rèn)有一個根作用域 $rootScope,根作用域位于最頂層,從它向下掛著各級作用域。所以,如果子控制器直接使用 $rootScope廣播和接收事件,那么就可實現(xiàn)平級之間的通信。9、一個 Angular應(yīng)用應(yīng)當(dāng)如何進(jìn)行目錄結(jié)構(gòu)的劃分?對于小型項目,可以按照文件類型劃分,比如以下形式。CSSJS controllers models services filters templates
但是,對于規(guī)模較大的項目,最好按業(yè)務(wù)模塊劃分,比如以下形式。CSS modules user controllers models services filters templates activity controllers models services filters templates
modules下最好再有一個 common目錄來存放公共數(shù)據(jù)。10、Angular應(yīng)用通常使用哪些路由庫?各自的區(qū)別是什么?Angular應(yīng)用通常使用 neRoute和 ui.router。無論是 ngRoute還是ui. router,作為框架額外的附加功能,都必須以模塊依賴的形式引入。(1)ngRoute模塊是 Angular自帶的路由模塊,而 ui.router模塊是基于 ngRoute模塊開發(fā)的第三方模塊,屬于UI指令規(guī)范。(2) ui.router是基于狀態(tài)( state)的, ngRoute是基于URL的, ui.router模塊具有更強(qiáng)大的功能,主要體現(xiàn)在視圖的嵌套方面。(3)使用 ui.router能夠定義有明確父子關(guān)系的路由,并通過ui-view指令將子路由模板插入父路由模板的<diⅳ ui-view</dⅳ>中,從而實現(xiàn)視圖嵌套。而在 neRoute中不能這樣定義,如果同時在父子視圖中使用了<diⅳ ng-view></diⅴ>會陷入死循環(huán)。ngRoute angular .module('ickt',[' ngRoute']).config(function ($routeProvider){$routeprovider.when(' / home', { template:'<hl>home { { color } }</h1>',controller:function($scope){$scope. color ='red'}}).otherwise ({redirectTo:'/home'}) ui .router angular .module('ickt',[ 'ui .router' ] ).config ( function($stateProvider ) {$stateProvider .state (' home',{url:'/home/:id?a&b, template:'<h1>home page { { color } }</h1>' ,//定義控制器controller:function($scope){$scope. color ='red'}})})
11、對于不同團(tuán)隊開發(fā)的 Angular應(yīng)用,如果要做整合,可能會遇到哪些問題?如何解決?可能會遇到不同模塊之間的沖突比如一個團(tuán)隊的開發(fā)在 moduleA下進(jìn)行,另一團(tuán)隊的開發(fā)在 moduleB下進(jìn)行。angular .module('myApp.moduleA', [ ] ).factory('serviceA, function ( ) {...} )angular .module('myApp. moduleB', [ ] ).factory('serviceA ', function( ) {...})angular .module('myApp,[' myApp. moduleA','myApp. moduleB'])
這會導(dǎo)致兩個 module下面的 serviceA發(fā)生覆蓋。在 Angular 1.x中并沒有很好的解決辦法,所以最好在前期進(jìn)行統(tǒng)一規(guī)劃,做好約定,嚴(yán)格按照約定開發(fā),每個開發(fā)人員只寫特定的區(qū)塊代碼。12、Angular的缺點有哪些?如何克服這些缺點?強(qiáng)約束,導(dǎo)致學(xué)習(xí)成本較高,對前端不友好。當(dāng)遵守 Angular的約定時,效率會提高。但不利于SEO,因為所有內(nèi)容都是動態(tài)獲取并渲染生成的,搜索引擎無法爬取種解決辦法是,對于正常用戶的訪問,服務(wù)器響應(yīng) Angular應(yīng)用的內(nèi)容;對于搜索引擎的訪問,則響應(yīng)專門針對SEO的HTML頁面。作為MVVM框架,因為實現(xiàn)了數(shù)據(jù)的雙向綁定,對于大數(shù)組、復(fù)雜對象會存在性能問題。13、如何優(yōu)化 Angular應(yīng)用的性能?(1)減少監(jiān)控項(比如對不會變化的數(shù)據(jù)采用單向綁定)。(2)主動設(shè)置索引(指定 track by,簡單類型默認(rèn)用自身當(dāng)索引,對象默認(rèn)使用 $$hashKey,比如改為 track by item id)。(3)降低渲染數(shù)據(jù)量(比如分頁,或者毎次取一小部分?jǐn)?shù)據(jù),根據(jù)需要再取)。(4)數(shù)據(jù)扁平化(比如對于樹狀結(jié)構(gòu),使用扁平化結(jié)構(gòu),構(gòu)建map和樹狀數(shù)據(jù)。當(dāng)操作樹時,由于跟扁平數(shù)據(jù)是同一個引用,因此樹狀數(shù)據(jù)變更會同步到原始的扁平數(shù)據(jù))。14、如何看待 Angular1.2中引入的 controllerAs語法?在 Angular1.2以前,在view上的任何綁定都是直接綁定在 $scope上的。function myCtrl($scope){ $scope.a=='aaa';$scope.foo = function ( ) {... }}
使用 controllerAs,不需要再注入 $scope服務(wù)了, controller變成了一個很簡單的 JavaScript對象,一個更純粹的ViewModel 。var vm = this; vm.a = 'aaa';
從源碼實現(xiàn)上來看, controllerAs語法只是把 controller這個對象的實例用 controllerAs別名表示,并在 $scope上創(chuàng)建了一個屬性。if (directive .controllerAs){locals. $scope [ directive .controllerAs ]= controllerInstance;}
與 Angular 1.x相比, Angular 2的改動很大,幾乎是一個全新的框架。Angular2基于 TypeScript語法實現(xiàn),在大型項目團(tuán)隊協(xié)作時,使用強(qiáng)語言類型更有利優(yōu)點是組件化,提升開發(fā)和維護(hù)的效率。其他優(yōu)點還有 module支持動態(tài)加載,以及new router、 promise的原生支持等。它迎合未來標(biāo)準(zhǔn),吸納其他框架的優(yōu)點,值得期待。16、表達(dá)式{ {data} }是如何工作的?它依賴于 $interpolation服務(wù),在初始化頁面HTML后,它會找到這些表達(dá)式,并進(jìn)行標(biāo)記,于是每遇見一個{{} },就會設(shè)置一個$ watch。而 $interpolation會返回一個帶有上下文參數(shù)的函數(shù),最后執(zhí)行該函數(shù),渲染數(shù)據(jù)。17、Angular中的 digest周期是如何觸發(fā)的?在每個 digest周期中, Angular總會對比 scope上 model的值,一般 digest周期都是自動觸發(fā)的,也可以使用 $apply進(jìn)行手動觸發(fā)。要停止$timeout,可以用 cancel方法。示例如下。var timebar =$timeout ( function ( ){$scope,msg='有課前端網(wǎng)'},1000)$timeout.cancel(timebar)
var watchFn = $scope. $watch('msg ', function(newValue) {if (newValue ==='icketang){// $watch()會返回一個停止注冊的函數(shù),可以執(zhí)行該函數(shù)進(jìn)行注銷watchFn ( )}console. log(newValue)} )
當(dāng)然,可以設(shè)置多個值,比如AEC,進(jìn)行多個匹配。21、自定義指令中, scope配置中的@、=和&修飾符有什么區(qū)別?在 scope中,@、=和&在進(jìn)行值綁定時分別表示如下含義。@表示單向綁定,數(shù)據(jù)只能由父作用域流入子作用域。=表示雙向綁定,數(shù)據(jù)可以在父子作用域中雙向傳遞。&表示父作用域傳遞的屬性或方法等數(shù)據(jù),在子作用域中作為方法獲取。22、請列岀至少3種實現(xiàn)不同模塊之間通信的方式。通過自定義服務(wù)實現(xiàn)作用域之間的通信。通過$on注冊事件,在其他作用域之間通過使用$emit或$broadcast發(fā)布消息實現(xiàn)通信。借助 $rootScope實現(xiàn)作用域間的通信。通過 $scope的$parent等屬性,訪問父子或者兄弟作用域,實現(xiàn)通信。(1)關(guān)閉 debug,方法是使用 $compileProvider 。myApp. config(function ($compileProvider){ $compileProvider .debugInfoEnabled(false);});
(2)使用一次綁定表達(dá)式,即{{:msg}。(4)在無限滾動加載中避免使用 ng-repeat(5)使用性能測試小工具挖掘 Angular的性能問題。24、你認(rèn)為在 Angular中使用 jQuery好嗎?普遍認(rèn)為在 Angular中使用 jQuery并不是一個很好的嘗試。其實當(dāng)我們學(xué)習(xí)Angular的時候,應(yīng)該做到從零去接受 Angular的思想,例如,數(shù)據(jù)綁定、使用 Angular自帶的一些API、合理地組織路由、寫相關(guān)指令和服務(wù)等。Angular自帶的很多API完全可以替代 jQuery中常用的API,可以使用 angular.element、$http、 $timeout、ng-init等。或許引入 jQuery可以在解決問題(比如使用插件)時有更多的選擇。當(dāng)然,這通過影響代碼組織來提高工作效率。隨著對 Angular的理解深入,在重構(gòu)時會逐漸摒棄當(dāng)初引入 jQuery時的一些代碼。所以我們還是應(yīng)該盡力遵循 Angular的設(shè)計理念。25、Angular的數(shù)據(jù)雙向綁定是如何實現(xiàn)的?(1)每個雙向綁定的元素都有一個 watcher。(2)在某些事件發(fā)生的時候,調(diào)用 digest對臟數(shù)據(jù)進(jìn)行檢測。這些事件有表單元素內(nèi)容變化、Ajax請求響應(yīng)、單擊按鈕執(zhí)行回調(diào)函數(shù)等。(3)臟數(shù)據(jù)檢測,會檢測 rootscope下所有被 watcher監(jiān)控的元素。$digest函數(shù)就是臟數(shù)據(jù)檢測函數(shù)。26、Angular中的$http服務(wù)有什么作用?$http是 Angular中的一個核心服務(wù),用于讀取遠(yuǎn)程服務(wù)器的數(shù)據(jù)。可以使用內(nèi)置的 $http服務(wù)直接與服務(wù)器端進(jìn)行通信。$http服務(wù)只是簡單地封裝了瀏覽器原生的 XMLHttpRequEst對象。27、在寫 controller邏輯時,需要注意什么?DOM操作只能出現(xiàn)在指令( directive)中。不應(yīng)該出現(xiàn)在服務(wù)( service)中。Angular倡導(dǎo)以測試驅(qū)動開發(fā),在服務(wù)或者控制器中出現(xiàn)了DOM操作,也就意味著無法通過測試。當(dāng)然,這只是一方面。重要的是,使用 Angular中的數(shù)據(jù)雙向綁定技術(shù),就能專注于處理業(yè)務(wù)邏輯,無須關(guān)心各種DOM操作。如果在 Angular的代碼中還有各種DOM操作,還不如直接使用 jQuery去開發(fā)。restrict:定義指令在DOM中的聲明形式,如E(元素)、A(屬性)、C(類名)、 M(注釋)。compile:可以返回一個對象或函數(shù)。如果設(shè)置了 compile函數(shù),說明我們希望在指令將數(shù)據(jù)綁定到DOM之前,進(jìn)行DOM操作,在這個函數(shù)中進(jìn)行諸如添加和刪除節(jié)點等DOM操作是安全的。link:鏈接函數(shù),可以實現(xiàn)指令的一些功能。29、Angular和 jQuery的區(qū)別是什么?Angular基于數(shù)據(jù)驅(qū)動,所以 Angular適合做數(shù)據(jù)操作比較繁雜的項目。jQuery基于DOM驅(qū)動, jQuery適合做DOM操作多的項目。30、什么是作用域數(shù)據(jù)丟失?如何解決作用域數(shù)據(jù)丟失問題?當(dāng)在作用域中修改數(shù)據(jù)的時候,更新的數(shù)據(jù)沒有渲染到頁面中,或者沒有觸發(fā)相應(yīng)的業(yè)務(wù)邏輯執(zhí)行,我們就說這部分?jǐn)?shù)據(jù)丟失了。解決數(shù)據(jù)丟失問題有4種方式。使用相應(yīng)的服務(wù),如 setTimeout方法可以用 $timeout服務(wù)完美代替。使用$digest方法進(jìn)行檢測,但只能檢測該方法執(zhí)行前修改的數(shù)據(jù),后面修改的數(shù)據(jù)無法檢測。使用$apply方法進(jìn)行檢測,但只能檢測該方法執(zhí)行前修改的數(shù)據(jù),后面修改的數(shù)據(jù)無法檢測,本質(zhì)上,$apply在內(nèi)部調(diào)用$digest方法實現(xiàn)檢測在 Sapply方法的回調(diào)函數(shù)中修改數(shù)據(jù),$apply方法可以屏蔽錯誤中斷應(yīng)用程序的執(zhí)行,但只能檢測前面以及回調(diào)函數(shù)內(nèi)部修改的數(shù)據(jù),在該方法后面修改的數(shù)據(jù)無法檢測。31、Angular2應(yīng)用程序的生命周期 hooks是什么?Angular2組件/指令具有生命周期事件,是由@ angular/core管理的。@ Angular/core會創(chuàng)建組件,渲染它,創(chuàng)建并呈現(xiàn)它的后代。當(dāng)@ angular/core的數(shù)據(jù)綁定屬性更改時,處理就會更改,在從DOM中刪除其模板之前,就會銷毀它。Angular提供了一組生命周期hooks(特殊事件)函數(shù),并在需要時執(zhí)行操作。構(gòu)造函數(shù)會在所有生命周期事件之前執(zhí)行。每個接口都有一個前綴為ng的hook方法。ngAfterContentInit:組件內(nèi)容初始化完成之后。
ngAfterContentChecked:在 Angular檢查投影到其視圖中綁定的數(shù)據(jù)之后。
ngAfterViewInitAngular:創(chuàng)建組件的視圖后。
ngAfterViewChecked:在 Angular檢查組件視圖的綁定之后。
32、和使用 Angular1相比,使用 Angular2有什么優(yōu)勢?Angular2是一個平臺,它不僅是一種語言,還具有更快的速度、更好的性能和更簡單的依賴注入。它支持模塊化開發(fā),跨平臺,具備了 EMAScript6和 Typescript的優(yōu)點,如路由靈活,具備延遲加載功能等。路由是能夠讓用戶在視圖紐組件之間導(dǎo)航的機(jī)制。Angular2簡化了路由,并提供了在模抉級的(延遲加載)配置,定義更靈活。Angular應(yīng)用程序具有路由器服務(wù)的單個實例,并且每當(dāng)URL改變時,相應(yīng)的路由就與路由配置數(shù)組進(jìn)行匹配。在成功匹配時,它會應(yīng)用重定向。此時,路由器會構(gòu)建 ActivatedRoute對象的樹,同時包含路由器的當(dāng)前狀態(tài)。在重定向之前,路由器將通過運行保護(hù)( CanActivate)來檢查是否允許新的狀態(tài)。Route Guard只是用來檢查路由授權(quán)的接口方法。保護(hù)運行后,它將解析路由數(shù)據(jù)并通過將所需的組件實例化到< router-outlet>< router- outlet>中來激活路由器狀態(tài)。34、什么是事件發(fā)射器?它是如何在 Angular2中工作的?Angular2不具有雙向檢測系統(tǒng),這與 Angular1不同。在 Angular2中,組件中發(fā)生的任何改變總是從當(dāng)前組件傳播到其所有的子組件中。如果一個子組件的更改需要反映到其父組件的層次結(jié)構(gòu)中,就可以使用事件發(fā)射器API(吞吐器)來發(fā)出事件簡而言之, EventEmitter是在@ angular/core模塊中定義的類,由組件和指令使用,用來發(fā)出自定義事件。使用emit( value)方法發(fā)出事件。通過模塊的任何一個組件,可以使用訂閱方法來實現(xiàn)事件發(fā)射的訂閱,例如以下代碼@Directive ({selector:'[app Demo]',outputs:[ 'sendMessage' ]})export class DemoDirective {sendMessage = new EventEmitter ( ) ;constructor ( ) {setInterval(o=>},2000)<hI (sendMessage)="receiveMessage() appDemo >demo</h1>export class AppComponent i//定義接收數(shù)據(jù)的方法receiveMessage() t console. log(' success)
大多數(shù)企業(yè)應(yīng)用程序包含各種用于特定業(yè)務(wù)案例的模塊。捆綁整個應(yīng)用程序代碼并完成加載,會在初始調(diào)用時,產(chǎn)生巨大的性能開銷。延遲加載使我們只加載用戶正在交互的模塊,而其余的模塊會在運行時按需加載延遲加載通過將代碼拆分成多個包并以按需加載的方式,來加速應(yīng)用程序初始加載過程。36、在 Angular2應(yīng)用中,應(yīng)該注意哪些安全威脅?就像任何其他客戶端或Web應(yīng)用程序一樣,Angular2應(yīng)用程序也應(yīng)該遵循一些基本準(zhǔn)則來減輕安全風(fēng)險,例如以下基本準(zhǔn)則。避免為組件使用/注入動態(tài)HTML內(nèi)容。如果使用外部HTML,也就是來自數(shù)據(jù)庫或應(yīng)用程序之外的HTML,就需要清理它。不要將外部網(wǎng)址放在應(yīng)用程序中,除非它是受信任的。通過限制API,選擇使用已知或安全環(huán)境/瀏覽器的App來防止XSRF攻擊。37、如何優(yōu)化 Angular2應(yīng)用程序來獲得更好的性能?優(yōu)化取決于應(yīng)用程序的類型和大小以及許多其他因素。但一般來說,在優(yōu)化Angular2應(yīng)用程序時,應(yīng)考慮以下幾點。確保應(yīng)用程序已經(jīng)進(jìn)行了捆綁。確保應(yīng)用程序不存在不必要的 import語句。確保應(yīng)用中已經(jīng)移除了不使用的第三方庫。所有 dependencies和dev- dependencies都是明確分離的。如果應(yīng)用程序較大,建議考慮延遲加載而不是完全捆綁的應(yīng)用程序。38、什么是 Shadow dom?它是如何幫助 Angular2更好地執(zhí)行的?Shadow DOM是HTML規(guī)范的一部分,它允許開發(fā)人員封裝自己的HTML標(biāo)記、 CSS和 JavaScript代碼。Shadow DOM以及其他一些技術(shù),使開發(fā)人員能夠像< audio>標(biāo)簽樣構(gòu)建自己的一級標(biāo)簽、Web組件和API??偟膩碚f,這些新的標(biāo)簽和API稱為Web組件。Shadow dom提供了更好的關(guān)注分離,通過其他的 HTML DOM元素實現(xiàn)了更少的樣式與腳本的沖突。因為 Shadow DOM本質(zhì)上是靜態(tài)的,同時也是開發(fā)人員無法訪問的,所以它是一個很好的候選對象。它緩存的DOM將在瀏覽器中呈現(xiàn)得更快,并提供更妤的性能。此外,還可以較好地管理 Shadow dom,同時檢測 Angular2應(yīng)用的改變,并且可以有效地管理視圖的重新繪制。39、什么是AOT編譯?它有什么優(yōu)缺點?AOT編譯,即 Ahead Of Time編譯(運行前編譯)。在構(gòu)建時, Angular編譯器會將 Angular組件和模板編譯為原生 JavaScript和HTML。編譯好的HTML和 JavaScript將會部署到Web服務(wù)器中,以便瀏覽器節(jié)省編譯和渲染時間。更快的下載速度。因為應(yīng)用程序已經(jīng)編譯,許多 Angular編譯器相關(guān)庫就不再需要捆綁,應(yīng)用程序包變得更小,所以該應(yīng)用程序可以更快地下載。更少的HTTP請求數(shù)。如果沒有捆綁應(yīng)用程序來支持延遲加載,對于每個關(guān)聯(lián)的HTML和CSS,都會有一個單獨的服務(wù)器請求。但是預(yù)編譯的應(yīng)用程序會將所有模板和樣式與組件對齊,因此到達(dá)服務(wù)器的HTTP請求數(shù)量會更少。更快的渲染速度。如果應(yīng)用程序不使用AOT編譯,那么應(yīng)用程序完全加載時,編譯過程會發(fā)生在瀏覽器中。這需要等待下載所有必需的組件,然后等待編譯器花費大量時間來編譯應(yīng)用程序。使用AOT編譯,就能實現(xiàn)優(yōu)化。在構(gòu)建時檢測錯誤。由于預(yù)先編譯可以檢測到許多編譯時錯誤,因此能夠為應(yīng)用程序提供更好的穩(wěn)定性。僅適用于HTML和CSS,其他文件類型需要前面的構(gòu)建步驟。沒有 watch模式,必須手動執(zhí)行并編譯所有文件。需要維護(hù)AOT版本的 bootstrap文件。40、如何評價 Backbone和 Angular?Backbone具有依賴性,依賴于 underscore.js。Backbone+ Underscore+ jQuery(或Zepto)比一個Angular應(yīng)用多出了兩次HTTP請求。Backbone的模型沒有與UI視圖數(shù)據(jù)綁定,而是需要在視圖中自行操作DOM來更新或讀取UⅠ數(shù)據(jù)。Angular與此相反,模型直接與UⅠ視圖綁定。模型與U視圖的關(guān)系,通過指令封裝。Angular內(nèi)置的通用指令就能實現(xiàn)大部分操作了。也就是說,基本不必關(guān)心視圖與UI視圖的關(guān)系,直接操作視圖即可,UI視圖自動更新。在你輸入特定數(shù)據(jù)時, Angular的指令就能渲染相應(yīng)的U視圖。它是一個比較完善的前端MVW框架,包含模板、數(shù)據(jù)雙向綁定、路由、模塊化、服務(wù)、依賴注入等功能模板的功能強(qiáng)大,并且是聲明式的,自帶豐富的Aη gular指令。41、談?wù)?ionic和 Angular的區(qū)別。ionic是一個用來開發(fā)混合手機(jī)應(yīng)用的、開源的、免費的代碼庫。可以優(yōu)化HTML、 CSS和 JavaScript的性能,構(gòu)建高效的應(yīng)用程序。Angular通過新的屬性和表達(dá)式擴(kuò)展了HTML. Angular可以構(gòu)建一個單一頁面應(yīng)用程序( Single Page Application,SPA)。ionic是一個混合App開發(fā)工具,它以 Angular為中間腳本工具,所以如果要使用 ionic開發(fā)App,就必須了解 Angular。42、在用雙大括號綁定元素時,如何解決內(nèi)容閃爍的問題?在 Angular內(nèi)部,可以向元素中添加ng- clock屬性來實現(xiàn)元素的隱藏效果。<div ng-clock> { {message } } </div>如果綁定純文字的內(nèi)容,建議使用ng-bind的方式,而非雙大括號。<div ng-bind="message"></div>
43、如何理解ng-repeat指令中的作用域繼承關(guān)系?在調(diào)用 ng-repeat指令顯示數(shù)據(jù)時,在新建DOM元素時, ng-repeat也為每個新建的DOM元素創(chuàng)建了獨立的作用域。盡管如此,它們的父級作用域是相同的,都是構(gòu)建控制器時注入的$scope對象,調(diào)用 angular.element( element).scope方法可以獲取某個DOM元素對應(yīng)的作用域。通過某個DOM元素對應(yīng)的作用域又可以訪問它的父級作用域,從而修改綁定的數(shù)據(jù)源。Angular是一個比較完善的前端MVVM框架,包含了模板、數(shù)據(jù)雙向綁定、路由、服務(wù)、過濾器、依賴注入等功能。與其他一些只關(guān)注前端某一方面的框架相比, Angular4支持的功能更加全面廣泛。