欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

AngularJS 面試題集錦

 更新時間:2016年09月06日 09:46:04   投稿:lqh  
本文主要介紹AngularJS的面試題資料整理,這里整理了相關(guān)面試題的資料,幫助大家學習理解AngularJS的知識,有興趣的小伙伴可以參考下

ng-if 跟 ng-show/hide 的區(qū)別有哪些?

第一點區(qū)別是, ng-if 在后面表達式為 true 的時候才創(chuàng)建這個 dom 節(jié)點, ng-show 是初始時就創(chuàng)建了,用 display:block 和 display:none 來控制顯示和不顯示。

第二點區(qū)別是, ng-if 會(隱式地)產(chǎn)生新作用域, ng-switch 、 ng-include 等會動態(tài)創(chuàng)建一塊界面的也是如此。

這樣會導致,在 ng-if 中用基本變量綁定 ng-model ,并在外層 div 中把此 model 綁定給另一個顯示區(qū)域,內(nèi)層改變時,外層不會同步改變,因為此時已經(jīng)是兩個變量了。

<p>{{name}}</p>
<div ng-if="true">
  <input type="text" ng-model="name">
</div>

ng-show 不存在此問題,因為它不自帶一級作用域。

避免這類問題出現(xiàn)的辦法是,始終將頁面中的元素綁定到對象的屬性(data.x)而不是直接綁定到基本變量(x)上。

詳見 AngularJS 中的作用域

ng-repeat迭代數(shù)組的時候,如果數(shù)組中有相同值,會有什么問題,如何解決?

會提示 Duplicates in a repeater are not allowed. 加 track by $index 可解決。當然,也可以 trace by 任何一個普通的值,只要能唯一性標識數(shù)組中的每一項即可(建立 dom 和數(shù)據(jù)之間的關(guān)聯(lián))。

ng-click 中寫的表達式,能使用 JS 原生對象上的方法嗎?

不止是 ng-click 中的表達式,只要是在頁面中,都不能直接調(diào)用原生的 JS 方法,因為這些并不存在于與頁面對應的 Controller 的 $scope 中。

舉個栗子:

<p>{{parseInt(55.66)}}<p>

會發(fā)現(xiàn),什么也沒有顯示。

但如果在 $scope 中添加了這個函數(shù):

$scope.parseInt = function(x){
  return parseInt(x);
}

這樣自然是沒什么問題了。

對于這種需求,使用一個 filter 或許是不錯的選擇:

<p>{{13.14 | parseIntFilter}}</p>

app.filter('parseIntFilter', function(){
  return function(item){
    return parseInt(item);
  }
})

{{now | 'yyyy-MM-dd'}} 這種表達式里面,豎線和后面的參數(shù)通過什么方式可以自定義?

filter,格式化數(shù)據(jù),接收一個輸入,按某規(guī)則處理,返回處理結(jié)果。

內(nèi)置 filter

ng 內(nèi)置的 filter 有九種:

date(日期)

currency(貨幣)

limitTo(限制數(shù)組或字符串長度)

orderBy(排序)

lowercase(小寫)

uppercase(大寫)

number(格式化數(shù)字,加上千位分隔符,并接收參數(shù)限定小數(shù)點位數(shù))

filter(處理一個數(shù)組,過濾出含有某個子串的元素)

json(格式化 json 對象)

filter 有兩種使用方法,一種是直接在頁面里:

<p>{{now | date : 'yyyy-MM-dd'}}</p>

另一種是在 js 里面用:

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

自定義 filter

// 形式
app.filter('過濾器名稱',function(){
  return function(需要過濾的對象,過濾器參數(shù)1,過濾器參數(shù)2,...){
    //...做一些事情 
    return 處理后的對象;
  }
}); 

// 栗子
app.filter('timesFilter', function(){
  return function(item, times){
    var result = '';
    for(var i = 0; i < times; i++){
      result += item;
    }
    return result;
  }
})

factory、service 和 provider 是什么關(guān)系?

factory

把 service 的方法和數(shù)據(jù)放在一個對象里,并返回這個對象

app.factory('FooService', function(){
  return {
    target: 'factory',
    sayHello: function(){
      return 'hello ' + this.target;
    }
  }
});

service

通過構(gòu)造函數(shù)方式創(chuàng)建 service,返回一個實例化對象

app.service('FooService', function(){
  var self = this;
  this.target = 'service';
  this.sayHello = function(){
    return 'hello ' + self.target;
  }
});

provider

創(chuàng)建一個可通過 config 配置的 service,$get 中返回的,就是用 factory 創(chuàng)建 service 的內(nèi)容

app.provider('FooService', function(){
  this.configData = 'init data';
  this.setConfigData = function(data){
    if(data){
      this.configData = data;
    }
  }
  this.$get = function(){
    var self = this;
    return {
      target: 'provider',
      sayHello: function(){
        return self.configData + ' hello ' + this.target;
      }
    }
  }
});

// 此處注入的是 FooService 的 provider
app.config(function(FooServiceProvider){
  FooServiceProvider.setConfigData('config data');
});

從底層實現(xiàn)上來看,service 調(diào)用了 factory,返回其實例;factory 調(diào)用了 provider,返回其 $get 中定義的內(nèi)容。factory 和 service 功能類似,只不過 factory 是普通 function,可以返回任何東西(return 的都可以被訪問,所以那些私有變量怎么寫,你懂的);service 是構(gòu)造器,可以不返回(綁定到 this 的都可以被訪問);provider 是加強版 factory,返回一個可配置的 factory。

詳見 AngularJS 之 Factory vs Service vs Provider

angular 的數(shù)據(jù)綁定采用什么機制?詳述原理

臟檢查機制。

雙向數(shù)據(jù)綁定是 AngularJS 的核心機制之一。當 view 中有任何數(shù)據(jù)變化時,會更新到 model ,當 model 中數(shù)據(jù)有變化時,view 也會同步更新,顯然,這需要一個監(jiān)控。

原理就是,Angular 在 scope 模型上設(shè)置了一個 監(jiān)聽隊列,用來監(jiān)聽數(shù)據(jù)變化并更新 view 。每次綁定一個東西到 view 上時 AngularJS 就會往 $watch 隊列里插入一條 $watch ,用來檢測它監(jiān)視的 model 里是否有變化的東西。當瀏覽器接收到可以被 angular context 處理的事件時, $digest 循環(huán)就會觸發(fā),遍歷所有的 $watch ,最后更新 dom。

舉個栗子

<button ng-click="val=val+1">increase 1</button>

click 時會產(chǎn)生一次更新的操作(至少觸發(fā)兩次 $digest 循環(huán))

按下按鈕

瀏覽器接收到一個事件,進入到 angular context

$digest 循環(huán)開始執(zhí)行,查詢每個 $watch 是否變化

由于監(jiān)視 $scope .val 的 $watch 報告了變化,因此強制再執(zhí)行一次 $digest 循環(huán)

新的 $digest 循環(huán)未檢測到變化

瀏覽器拿回控制器,更新 $scope .val 新值對應的 dom

$digest 循環(huán)的上限是 10 次(超過 10次后拋出一個異常,防止無限循環(huán))。

詳見 關(guān)于 AngularJS 的數(shù)據(jù)綁定

兩個平級界面塊 a 和 b,如果 a 中觸發(fā)一個事件,有哪些方式能讓 b 知道?詳述原理

這個問題換一種說法就是,如何在平級界面模塊間進行通信。有兩種方法,一種是共用服務,一種是基于事件。

共用服務

在 Angular 中,通過 factory 可以生成一個單例對象,在需要通信的模塊 a 和 b 中注入這個對象即可。

基于事件

這個又分兩種方式

第一種是借助父 controller。在子 controller 中向父 controller 觸發(fā)( $emit )一個事件,然后在父 controller 中監(jiān)聽( $on )事件,再廣播( $broadcast )給子 controller ,這樣通過事件攜帶的參數(shù),實現(xiàn)了數(shù)據(jù)經(jīng)過父 controller,在同級 controller 之間傳播。

第二種是借助 $rootScope 。每個 Angular 應用默認有一個根作用域 $rootScope , 根作用域位于最頂層,從它往下掛著各級作用域。所以,如果子控制器直接使用 $rootScope 廣播和接收事件,那么就可實現(xiàn)同級之間的通信。

詳見 AngularJS 中 Controller 之間的通信

一個 angular 應用應當如何良好地分層?

目錄結(jié)構(gòu)的劃分

對于小型項目,可以按照文件類型組織,比如:

css
js
 controllers
 models
 services
 filters
templates 

但是對于規(guī)模較大的項目,最好按業(yè)務模塊劃分,比如:

css
modules
 account
  controllers
  models
  services
  filters
  templates
 disk
  controllers
  models
  services
  filters
  templates

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

邏輯代碼的拆分

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

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

在復雜的應用中,也可以為實體建立對應的構(gòu)造函數(shù),比如硬盤(Disk)模塊,可能有列表、新建、詳情這樣幾個視圖,并分別對應的有 controller,那么可以建一個 Disk 構(gòu)造函數(shù),里面完成數(shù)據(jù)的增刪改查和驗證操作,有跟 Disk 相關(guān)的 controller,就注入 Disk 構(gòu)造器并生成一個實例,這個實例就具備了增刪改查和驗證方法。這樣既層次分明,又實現(xiàn)了復用(讓 controller 層更薄了)。

參考 AngularJS在蘇寧云中心的深入實踐

angular 應用常用哪些路由庫,各自的區(qū)別是什么?

Angular1.x 中常用 ngRoute 和 ui.router,還有一種為 Angular2 設(shè)計的 new router (面向組件)。后面那個沒在實際項目中用過,就不講了。

無論是 ngRoute 還是 ui.router,作為框架額外的附加功能,都必須以 模塊依賴 的形式被引入。

區(qū)別

ngRoute 模塊是 Angular 自帶的路由模塊,而 ui.router 模塊是基于 ngRoute模塊開發(fā)的第三方模塊。

ui.router 是基于 state (狀態(tài))的, ngRoute 是基于 url 的,ui.router模塊具有更強大的功能,主要體現(xiàn)在視圖的嵌套方面。

使用 ui.router 能夠定義有明確父子關(guān)系的路由,并通過 ui-view 指令將子路由模版插入到父路由模板的 <div ui-view></div> 中去,從而實現(xiàn)視圖嵌套。而在 ngRoute 中不能這樣定義,如果同時在父子視圖中 使用了 <div ng-view></div> 會陷入死循環(huán)。

示例

ngRoute

var app = angular.module('ngRouteApp', ['ngRoute']);
app.config(function($routeProvider){
  $routeProvider
    .when('/main', {
      templateUrl: "main.html",
      controller: 'MainCtrl'
    })
    .otherwise({ redirectTo: '/tabs' });

ui.router

var app = angular.module("uiRouteApp", ["ui.router"]);
app.config(function($urlRouterProvider, $stateProvider){
  $urlRouterProvider.otherwise("/index");
  $stateProvider
    .state("Main", {
      url: "/main",
      templateUrl: "main.html",
      controller: 'MainCtrl'
    })

如果通過angular的directive規(guī)劃一套全組件化體系,可能遇到哪些挑戰(zhàn)?

沒有自己用 directive 做過一全套組件,講不出。

能想到的一點是,組件如何與外界進行數(shù)據(jù)的交互,以及如何通過簡單的配置就能使用吧。

分屬不同團隊進行開發(fā)的 angular 應用,如果要做整合,可能會遇到哪些問題,如何解決?

可能會遇到不同模塊之間的沖突。

比如一個團隊所有的開發(fā)在 moduleA 下進行,另一團隊開發(fā)的代碼在 moduleB 下

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

會導致兩個 module 下面的 serviceA 發(fā)生了覆蓋。

貌似在 Angular1.x 中并沒有很好的解決辦法,所以最好在前期進行統(tǒng)一規(guī)劃,做好約定,嚴格按照約定開發(fā),每個開發(fā)人員只寫特定區(qū)塊代碼。

angular 的缺點有哪些?

強約束

導致學習成本較高,對前端不友好。

但遵守 AngularJS 的約定時,生產(chǎn)力會很高,對 Java 程序員友好。

不利于 SEO

因為所有內(nèi)容都是動態(tài)獲取并渲染生成的,搜索引擎沒法爬取。

一種解決辦法是,對于正常用戶的訪問,服務器響應 AngularJS 應用的內(nèi)容;對于搜索引擎的訪問,則響應專門針對 SEO 的HTML頁面。

性能問題

作為 MVVM 框架,因為實現(xiàn)了數(shù)據(jù)的雙向綁定,對于大數(shù)組、復雜對象會存在性能問題。

可以用來 優(yōu)化 Angular 應用的性能 的辦法:

減少監(jiān)控項(比如對不會變化的數(shù)據(jù)采用單向綁定)

主動設(shè)置索引(指定 track by ,簡單類型默認用自身當索引,對象默認使用 $$hashKey ,比如改為 track by item.id )

降低渲染數(shù)據(jù)量(比如分頁,或者每次取一小部分數(shù)據(jù),根據(jù)需要再?。?/p>

數(shù)據(jù)扁平化(比如對于樹狀結(jié)構(gòu),使用扁平化結(jié)構(gòu),構(gòu)建一個 map 和樹狀數(shù)據(jù),對樹操作時,由于跟扁平數(shù)據(jù)同一引用,樹狀數(shù)據(jù)變更會同步到原始的扁平數(shù)據(jù))

另外,對于Angular1.x ,存在 臟檢查 和 模塊機制 的問題。

移動端

可嘗試 Ionic,但并不完善。

參考 如何看2015年1月Peter-Paul Koch對Angular的看法?

如何看待 angular 1.2 中引入的 controller as 語法?

最根本的好處

在 angular 1.2 以前,在 view 上的任何綁定都是直接綁定在 $scope 上的

function myCtrl($scope){
  $scope.a = 'aaa';
  $scope.foo = function(){
    ...
  }
}

使用 controllerAs,不需要再注入 $scope ,controller 變成了一個很簡單的 javascript 對象(POJO),一個更純粹的 ViewModel。

function myCtrl(){
  // 使用 vm 捕獲 this 可避免內(nèi)部的函數(shù)在使用 this 時導致上下文改變
  var vm = this;
  vm.a = 'aaa';
}

原理

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

if (directive.controllerAs) {
  locals.$scope[directive.controllerAs] = controllerInstance;
}

但是這樣做,除了上面提到的使 controller 更加 POJO 外,還可以避免遇到 AngularJS 作用域相關(guān)的一個坑(就是上文中 ng-if 產(chǎn)生一級作用域的坑,其實也是 javascript 原型鏈繼承中值類型繼承的坑。因為使用 controllerAs 的話 view 上所有字段都綁定在一個引用的屬性上,比如 vm.xx,所以坑不再存在)。

<div ng-controller="TestCtrl as vm">
  <p>{{name}}</p>
  <div ng-if="vm.name">
    <input type="text" ng-model="vm.name">
  </div>
</div>

問題

使用 controllerAs 會遇到的一個問題是,因為沒有注入 $scope ,導致 $emit 、 $broadcast 、 $on 、 $watch 等 $scope 下的方法無法使用。這些跟事件相關(guān)的操作可以封裝起來統(tǒng)一處理,或者在單個 controller 中引入 $scope ,特殊對待。

參考 angular controller as syntax vs scope

詳述 angular 的 “依賴注入”

栗子

依賴注入是一種軟件設(shè)計模式,目的是處理代碼之間的依賴關(guān)系,減少組件間的耦合。

舉個栗子,如果沒有使用 AngularJS,想從后臺查詢數(shù)據(jù)并在前端顯示,可能需要這樣做:

var animalBox = document.querySelector('.animal-box');

var httpRequest = {
  get: function(url, callback){
    console.log(url + ' requested');
    var animals = ['cat', 'dog', 'rabbit'];
    callback(animals);
  }
}

var render = function(el, http){
  http.get('/api/animals', function(animals){
    el.innerHTML = animals;
  })
}

render(httpRequest, animalBox);

但是,如果在調(diào)用 render 的時候不傳參數(shù),像下面這樣,會報錯,因為找不到 el 和 http(定義的時候依賴了,運行的時候不會自動查找依賴項)

render();
// TypeError: Cannot read property 'get' of undefined

而使用 AngularJS,可以直接這樣

function myCtrl = ($scope, $http){
  $http.get('/api/animals').success(function(data){
    $scope.animals = data;
  })
}

也就是說,在 Angular App 運行的時候,調(diào)用 myCtrl,自動做了 $scope 和 $http 兩個依賴性的注入。

原理

AngularJS 是通過構(gòu)造函數(shù)的參數(shù)名字來推斷依賴服務名稱的,通過 toString() 來找到這個定義的 function 對應的字符串,然后用正則解析出其中的參數(shù)(依賴項),再去依賴映射中取到對應的依賴,實例化之后傳入。

簡化一下,大概是這樣:

var inject = {
  // 存儲依賴映射關(guān)系
  storage: {},  
  // 注冊依賴
  register: function(name, resource){
    this.storage[name] = resource;
  }, 
  // 解析出依賴并調(diào)用
  resolve: function(target){
  
    var self = this;
    
    var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
    var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
    fnText = target.toString().replace(STRIP_COMMENTS, '');
    argDecl = fnText.match(FN_ARGS)[1].split(/, ?/g);
    
    var args = [];
    argDecl.forEach(function(arg){
      if(self.storage[arg]){
        args.push(self.storage[arg]);
      }
    })
    
    return function(){
      target.apply({}, args);
    }
  }
}

使用這個 injector,前面那個不用 AngularJS 的栗子這樣改造一下就可以調(diào)用了

inject.register('el', animalBox);
inject.register('ajax', httpRequest);
render = inject.resolve(render);
render();

問題

因為 AngularJS 的 injector 是假設(shè)函數(shù)的參數(shù)名就是依賴的名字,然后去查找依賴項,那如果按前面栗子中那樣注入依賴,代碼壓縮后(參數(shù)被重命名了),就無法查找到依賴項了。

// 壓縮前
function myCtrl = ($scope, $http){
  ...
}

// 壓縮后
function myCtrl = (a, b){
  ...
}

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

數(shù)組注釋法

myApp.controller('myCtrl', ['$scope', '$http', function($scope, $http){
  ...
}])

顯式 $inject

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

補充

對于一個 DI 容器,必須具備三個要素:依賴項的注冊,依賴關(guān)系的聲明和對象的獲取。

在 AngularJS 中,module 和 $provide 都可以提供依賴項的注冊;內(nèi)置的 injector 可以獲取對象(自動完成依賴注入);依賴關(guān)系的聲明,就是前面問題中提到的那樣。

下面是個栗子

// 對于 module,傳遞參數(shù)不止一個,代表新建模塊,空數(shù)組代表不依賴其他模塊
// 只有一個參數(shù)(模塊名),代表獲取模塊

// 定義 myApp,添加 myApp.services 為其依賴項
angular.module('myApp', ['myApp.services']);
// 定義一個 services module,將 services 都注冊在這個 module 下面
angular.module('myApp.services', [])

// $provider 有 factory, service, provider, value, constant

// 定義一個 HttpService
angular.module('myApp.services').service('HttpService', ['$http', function($http){
  ...
}])

參考

[AngularJS] 自己實現(xiàn)一個簡單的依賴注入

理解angular中的module和injector,即依賴注入

AngularJS中的依賴注入實際應用場景

如何看待angular2

相比 Angular1.x,Angular2的改動很大,幾乎算是一個全新的框架。

基于 TypeScript(可以使用 TypeScript 進行開發(fā)),在大型項目團隊協(xié)作時,強語言類型更有利。

組件化,提升開發(fā)和維護的效率。

還有 module 支持動態(tài)加載,new router,promise的原生支持等等。

迎合未來標準,吸納其他框架的優(yōu)點,值得期待,不過同時要學習的東西也更多了(ES next、TS、Rx等)。

以上就是對AngularJS 面試題的資料整理,后續(xù)繼續(xù)補充相關(guān)資料謝謝大家對本站的支持!

相關(guān)文章

最新評論