angular常見問題

来源:http://www.cnblogs.com/rosann-33/archive/2017/04/06/6675280.html
-Advertisement-
Play Games

1. ng-if跟ng-show/hide的區別有哪些? 第一點區別是,ng-if 在後面表達式為 true 的時候才創建這個 dom 節點,ng-show 是初始時就創建了,用 display:block 和 display:none 來控制顯示和不顯示。 第二點區別是,ng-if 會(隱式地)產 ...


1. ng-if跟ng-show/hide的區別有哪些?
第一點區別是,ng-if 在後面表達式為 true 的時候才創建這個 dom 節點,ng-show 是初始時就創建了,用 display:block 和 display:none 來控制顯示和不顯示。
第二點區別是,ng-if 會(隱式地)產生新作用域,ng-switch 、 ng-include 等會動態創建一塊界面的也是如此。
## 2. ng-repeat迭代數組的時候,如果數組中有相同值,會有什麼問題,如何解決?
會提示 `Duplicates in a repeater are not allowed.` 加 `track by $index `可解決。當然,也可以 `trace by` 任何一個普通的值,只要能唯一性標識數組中的每一項即可(建立 dom 和數據之間的關聯)。
## 3. ng-click中寫的表達式,能使用JS原生對象上的方法,比如Math.max之類的嗎?為什麼?
不可以。只要是在頁面中,就不能直接調用原生的 JS 方法,因為這些並不存在於與頁面對應的 Controller 的 $scope 中。除非在 $scope 中添加了這個函數:
``` javascript
$scope.parseInt = function(x){
return parseInt(x);
} ```
## 4. {{now | 'yyyy-MM-dd'}}這種表達式裡面,豎線和後面的參數通過什麼方式可以自定義?

定義方式:
app.filter('過濾器名稱',function(){
return function(需要過濾的對象, 過濾器參數1, 過濾器參數2, ...){
//...做一些事情
return 處理後的對象;
}
});

使用方式有兩種,一種是直接在頁面里:
javascript<p>{{now | date : 'yyyy-MM-dd'}}</p>

一種是在 js 裡面用:

// $filter('過濾器名稱')(需要過濾的對象, 參數1, 參數2,...)
$filter('date')(now, 'yyyy-MM-dd hh:mm:ss');

## 5. factory和service,provider是什麼關係?

factory 把 service 的方法和數據放在一個對象里,並返回這個對象;service 通過構造函數方式創建 service,返回一個實例化對象;provider 創建一個可通過 config 配置的 service。

從底層實現上來看,service 調用了 factory,返回其實例;factory 調用了 provider,將其定義的內容放在 $get 中返回。factory 和 service 功能類似,只不過 factory 是普通 function,可以返回任何東西(return 的都可以被訪問,所以那些私有變數怎麼寫你懂的);service 是構造器,可以不返回(綁定到 this 的都可以被訪問);provider 是加強版 factory,返回一個可配置的 factory。
## 6. angular的數據綁定採用什麼機制?詳述原理臟檢查機制。

Angular 在 scope 模型上設置了一個監聽隊列,用來監聽數據變化並更新 view 。每次綁定一個東西到 view 上時 AngularJS 就會往 $watch 隊列里插入一條 $watch,用來檢測它監視的 model 里是否有變化的東西。當瀏覽器接收到可以被 angular context 處理的事件時,$digest 迴圈就會觸發,遍歷所有的 $watch,最後更新 dom。

舉個慄子:
<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. 兩個平級界面塊a和b,如果a中觸發一個事件,有哪些方式能讓b知道,詳述原理(這個問題換一種說法就是,如何在平級界面模塊間進行通信。)

有兩種方法,一種是共用服務,一種是基於事件。
a. 共用服務
在 Angular 中,通過 factory 可以生成一個單例對象,在需要通信的模塊 a 和 b 中註入這個對象即可。

b. 基於事件
這個又分兩種方式第一種是藉助父 controller。在子 controller 中向父 controller 觸發($emit)一個事件,然後在父 controller 中監聽($on)事件,再廣播($broadcast)給子 controller ,這樣通過事件攜帶的參數,實現了數據經過父 controller,在同級 controller 之間傳播。

第二種是藉助 $rootScope。每個 Angular 應用預設有一個根作用域 $rootScope, 根作用域位於最頂層,從它往下掛著各級作用域。所以,如果子控制器直接使用 $rootScope 廣播和接收事件,那麼就可實現同級之間的通信。
## 8. 一個angular應用應當如何良好地分層?

分兩個方面講
a.目錄結構的劃分

對於小型項目,可以按照文件類型組織,比如css
js
controllers
models
services
filters
templates

但是對於規模較大的項目,最好按業務模塊劃分,比如css
modules
account
controllers
models
services
filters
templates
disk
controllers
models
services
filters
templates

modules 下最好再有一個 common 目錄來存放公共的東西。

b. 邏輯代碼的劃分
作為一個 MVVM 框架,Angular 應用本身就應該按照 模型,視圖模型(控制器),視圖來劃分。

這裡邏輯代碼的拆分,主要是指儘量讓 controller 這一層很薄。提取共用的邏輯到 service 中 (比如後臺數據的請求,數據的共用和緩存,基於事件的模塊間通信等),提取共用的界面操作到 directive 中(比如將日期選擇、分頁等封裝成組件等),提取共用的格式化操作到 filter 中等等。

在複雜的應用中,也可以為實體建立對應的構造函數,比如硬碟(Disk)模塊,可能有列表、新建、詳情這樣幾個視圖,並分別對應的有 controller,那麼可以建一個 Disk 構造函數,裡面完成數據的增刪改查和驗證操作,有跟 Disk 相關的 controller,就註入 Disk 構造器並生成一個實例,這個實例就具備了增刪改查和驗證方法。這樣既層次分明,又實現了復用(讓 controller 層更薄了)。
## 9. 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 指令將子路由模版插入到父路由模板的 <div ui-view></div> 中去,從而實現視圖嵌套。而在 ngRoute 中不能這樣定義,如果同時在父子視圖中 使用了 <div ng-view></div> 會陷入死迴圈。
## 10. 如果通過angular的directive規劃一套全組件化體系,可能遇到哪些挑戰?

沒有自己用 directive 做過一全套組件,講不出。能想到的一點是,組件如何與外界進行數據的交互,以及如何通過簡單的配置就能使用吧。

## 11. 分屬不同團隊進行開發的angular應用,如果要做整合,可能會遇到哪些問題,如何解決?
可能會遇到不同模塊之間的衝突。比如一個團隊所有的開發在 moduleA 下進行,另一團隊開發的代碼在 moduleB 下:

angular.module('myApp.moduleA', [])
.factory('serviceA', function(){
...
})

angular.module('myApp.moduleB', [])
.factory('serviceA', function(){
...
})

angular.module('myApp', ['myApp.moduleA', 'myApp.moduleB'])

會導致兩個 module 下麵的 serviceA 發生了覆蓋。

貌似在 Angular1.x 中並沒有很好的解決辦法,所以最好在前期進行統一規劃,做好約定,嚴格按照約定開發,每個開發人員只寫特定區塊代碼。
## 12. angular的缺點有哪些?
a. 強約束
導致學習成本較高,對前端不友好。但遵守 AngularJS 的約定時,生產力會很高,對 Java 程式員友好。
b. 不利於 SEO
因為所有內容都是動態獲取並渲染生成的,搜索引擎沒法爬取。
一種解決辦法是,對於正常用戶的訪問,伺服器響應 AngularJS 應用的內容;對於搜索引擎的訪問,則響應專門針對 SEO 的HTML頁面。
c. 性能問題
作為MVVM框架,因為實現了數據的雙向綁定,對於大數組、複雜對象會存在性能問題。

可以用來 優化 Angular 應用的性能 的辦法:
減少監控項(比如對不會變化的數據採用單向綁定)
主動設置索引(指定 track by,簡單類型預設用自身當索引,對象預設使用 $$hashKey,比如改為track by item.id)
降低渲染數據量(比如分頁,或者每次取一小部分數據,根據需要再取)
數據扁平化(比如對於樹狀結構,使用扁平化結構,構建一個 map 和樹狀數據,對樹操作時,由於跟扁平數據同一引用,樹狀數據變更會同步到原始的扁平數據)

d. 移動端

## 13. 如何看待angular 1.2中引入的controller as 語法?
在 angular 1.2 以前,在 view 上的任何綁定都是直接綁定在 $scope 上的。使用 controllerAs,不需要再註入 $scope,controller 變成了一個很簡單的 javascript 對象(POJO),一個更純粹的 ViewModel。

從源碼實現上來看,controllerAs 語法只是把 controller 這個對象的實例用 as 別名在 $scope 上創建了一個屬性。

if (directive.controllerAs) {
locals.$scope[directive.controllerAs] = controllerInstance;
}
但是這樣做,除了上面提到的使 controller 更加 POJO 外,還可以避免遇到 AngularJS 作用域相關的一個坑(就是上文中 ng-if 產生一級作用域的坑,其實也是 javascript 原型鏈繼承中值類型繼承的坑。因為使用 controllerAs 的話 view 上所有欄位都綁定在一個引用的屬性上,比如 vm.xx,所以坑不再存在)。

不過不引入 $scope 會出現的一個問題是,導致 $emit、 $broadcast、 $on、$watch 等 $scope 下的方法無法使用。這些跟事件相關的操作可以封裝起來統一處理,或者在單個 controller 中引入 $scope,特殊對待。

## 14. 詳述angular的“依賴註入”
AngularJS 是通過構造函數的參數名字來推斷依賴服務名稱的,通過 toString() 來找到這個定義的 function 對應的字元串,然後用正則解析出其中的參數(依賴項),再去依賴映射中取到對應的依賴,實例化之後傳入。

因為 AngularJS 的 injector 是假設函數的參數名就是依賴的名字,然後去查找依賴項,那如果像下麵這樣簡單註入依賴,代碼壓縮後(參數被重命名了),就無法查找到依賴項了。

function myCtrl = ($scope, $http){
...
}

所以,通常會使用下麵兩種方式註入依賴(對依賴添加的順序有要求)。

數組註釋法:
myApp.controller('myCtrl', ['$scope', '$http', function($scope, $http){
...
}])

顯式 $inject :
myApp.controller('myCtrl', myCtrl);
function myCtrl = ($scope, $http){
...
}
myCtrl.$inject = ['$scope', '$http'];

對於一個 DI 容器,必須具備三個要素:依賴項的註冊,依賴關係的聲明和對象的獲取。在 AngularJS 中,module 和 $provide 都可以提供依賴項的註冊;內置的 injector 可以獲取對象(自動完成依賴註入);依賴關係的聲明,就是上面的那兩種方式。

## 15.controller as 和controller 有什麼區別,能解決什麼問題?

在使用controller的時候,為控制器註入$window與$scope,這個時候controller中的屬性與方法是屬於$scope的,而使用controllerAS的時候,可以將controller定義為Javascript的原型類,在html中直接綁定原型類的屬性和方法

優點:
a.可以使用 Javascript 的原型類, 我們可以使用更加高級的 ES6 或者 TypeScript 來編寫 Controller ;
b.避開了所謂的 child scope 原型繼承帶來的一些問題

Controller:
angular.module('app', []).controller('TestController', TestController);
TestController.$inject = ['$scope', '$window'];
function TestController($scope, $window) {
$scope.name = 'beginor';
$scope.greet = greet;
function greet() {
$window.alert('Hello, ' + $scope.name);
}
}
HTML中的使用:
<div ng-Controller="TestController">
<label>Name:
<input type="text" ng-model="name" />
</label>
<button type="button" ng-click="greet()">
</div>

controllerAS:
angular.module('app', []).controller('TestController', TestController);
TestController.$inject = ['$window'];
function TestController($window) {
this.name = 'beginor';
this.$window = $window;
}
TestController.prototype.greet = function () {
this.$window.alert('Hello, ' + this.name);
}
HTML中的使用:
<div ng-Controller="TestController as vm">
<label>Name:
<input type="text" ng-model="vm.name" />
</label>
<button type="button" ng-click="vm.greet()">
</div>

## 16.html: {{currentDate()}} js: $scope.currentDate = function(){return new Date();} 這種寫法有沒有問題?
有問題,時間是實時變化的,然後會一直更新數據,效率低,臟數據檢查到10次之後不再繼續檢查;
解決方案:可以使用一個變數來接收函數調用

## 17. directive 如何調用外部函數,如何向函數里傳遞參數,如何expose函數給外部調用?

## 18. 自定義指令裡面的compiled和link函數分別有什麼作用,它們的應用場景是怎麼樣的?

 

## 19. knockoutjs,angularjs,backbone,handlebars區別

knockoutjs:體積小,相容性好,業務代碼繁瑣,性能一般
backbone:輕量級應用
handlerbars:是一個模板庫,一般是一些靜態模板
angularjs:是框架,包含了模板這一快的東西,但是界面上不僅僅是只有模板,還包括一些配置的東西,可以被特定的方式


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...