Angularjs (一)

 

1、Angular是一款優秀的前端js框架,用它可以輕鬆構建SPA(Single Page Application,單頁面應用程序) ,它的特徵是:具有mvc的架構模式,便於模塊化開發,自動化雙向數據綁定和特有的指令系統。它最大限度的解放了Dom操作,讓js代碼更專注於業務邏輯的實現,通過簡單的指令,結合頁面結構和邏輯數據,通過自定義指令,實現組件化編程,代碼結構更合理,維護成本更低。

2、Angular的應用完全沒有自己寫dom操作的地方。通過一些ng指令來完成事件綁定以及賦值,當我們寫網頁或者其他Angular應用時應注意的就是程序邏輯的地方,而不用去關注dom操作,減少了大量的代碼量。這更符合面向對象編程,讓框架去處理dom而我們只去處理邏輯。

3、如何使用Angular
在HTML代碼中引入Angular.js包
在HTML代碼中將剛剛定義的模塊通過ng-app="yourModuleName"指令的方式作用到一個特定的元素上
在JS代碼中通過angular.module('yourModuleName', []) 註冊一個模塊
根據當前頁面的情況(業務塊)劃分控制器
在HTML代碼中將剛剛定義的控制器通過ng-controller="ControllerName"作用到特定的元素上
建模(根據界面原型抽象一個數據模型)得到一個視圖模型(ViewModel)
在JS代碼中通過$scope暴露需要提供到頁面的數據成員
在HTML代碼中將剛剛暴露出來的數據通過類似ng-model/{{}}/ng-click之類的指令綁定到特定的元素上
在JS中完成業務邏輯

4、ng中是怎麼樣處理指令的
當瀏覽器渲染一個頁面時,本質上是讀html標識,然後建立dom節點,當dom樹創建完畢之後廣播一個事件給我們.
當你在頁面中使用script標籤加載ng應用程序代碼時,ng監聽上面的dom完成事件,查找帶有ng-app屬性的元素.
當找到這樣的元素之後,ng開始處理dom以這個元素的起點,所以假如ng-app被添加到html元素上,則ng就會從html元素開始處理dom.
從這個起點開始,ng開始遞歸查找所有子元素裏面,符合應用程序裏定義好的指令規則.

5、angular程序的控制器必須在ng-app的範圍之內,否則失效。 
ng-model是用於表單的模型,用於代替表單的值,用作和程序之間交流的模型,可以進行雙向的數據綁定 。

 {{}}表達式只能夠單向的綁定數據。實現從邏輯層到視圖層的單向綁定,呈現數據。

6、service 
在angular中,service都是單例的,幾乎每一個學習的教程中都會提到這一點,
並加以強調。單例的意思是說,在整個的應用中,每一個service對象只會被實
例化一次,其他地方對這個對象的操作,會影響到全局。

7、service 、provider、factory  

 

首先,有個東西需要說一下。以往在Js中,我們寫了大量的代碼來存取變量值,在angular中我們找到了一個比較好的

 

方法。然後,剛開始寫angular的時候,我們容易把數據放的亂七八糟,有時候各種$scope, 各種域, 各種controller

 

的問題,這樣其實就失去了angular的優勢,angular的設計中 controller層是很薄的,一些業務邏輯的處理和數據持

 

化的問題需要放到service中。出於內存的考慮,controller只有在需要的時候纔會被初始化,不需要的的時候就會

 

被拋棄。所以說,當你刷新頁面時,controller就會被清空。而service就可以用來保存應用數據,並且可以在不同的

 

域中被使用。

 

(1)用Factory就是創建一個對象,添加了一定的屬性之後,把它返回回來。你把service傳進controller之後,在

 

controller裏這個對象裏的屬性就可以通過factory使用了。

 

app.controller('myFactoryctrl', function($scope, myfactory){
    $scope.artist = myFactory.getArtist();
});
app.factory('myfactory', fuction(){
    var _artist = '';
    var service = {};
    service.getArtist = fuction(){
        return _artist;
    }
    return service;
});

 

(2) service 是用‘new’ 關鍵字實例化的。因此,你應該給‘this’添加屬性,然後 service返回‘this’,把service傳進cont

roller之後,在controller裏的‘this’ 上的屬性就可以通過service來使用了。

app.controller('myServicectrl',function($scope, myService){
    $scope.artist =myService.getArtist();
});
app.service('myService', function(){
    var _artist = 'Nelly';
    this.getArtist = function(){
        return _artist;
    }
});

 

(3)provider 是唯一一種可以傳進config()函數的service。當你想要在service對象啓用之前,先進行模塊範圍的配

置,那就應該使用provider.

app.controller('myProviderCtrl', function($scope, myProvider){
    $scope.artist = myProvider.getArtist();
    $scope.data.thingFromConfig = myProvider.thingOnConfig;
});
app.provider('myProvider', function(){
    this._artist = '';
    this.thingFromConfig = '' ;
    this,$get = function(){
        var that = this;
        return {
        getArtist:function(){
            return that._artist;
        }
        thingOnConfig: that.thingFromConfig
    }
    }
});

app.config(function(myProviderProvider){
    myProviderProvider.thingFromConfig = 'this was set in config()';
});

 

最後,強調一點,當我們需要在不同的域中共享數據的時候,我們最好用 service來實現. 

8、關於directive裏的link和controller區別?

(1)、執行順序:先controller後link
(2)、何時使用controller:一般場景下都不想要使用controller,只需要把邏輯寫在link中就可以了;用controller的場景就是該指令(假設爲a)會被其他指令(假設爲b)require的時候,這樣就會在b指令的link函數中傳入這個controller(如果require多個的話,傳入的是一個數組,數組中存放的是每一個require的指令對應的controller),目的很顯然是爲了指令間進行交流的。

9、關於非directive的scope能否用link?
在指令中才存在調用link的時候,也就是說link是該指令在compile之後和scope進行綁定的時候調用的。
那只有在指令定義的那個地方用到link了,其他地方也可以用,例如做彈出框的時候就需要,拿到模板tpl,然後調用var linkFn = $compile(angular.element(tpl));此時返回的就是一個link的函數,然後linkFn(scope),這裏的scope是你需要指定的scope,可以是新創建的,也可以是已經存在的。

 

10、爲什麼編譯的過程要分成compile和link?

 

簡單的說就是爲了解決性能問題,特別是那種model變化會影響dom結構變化的,而變化的結構還會有新的scope綁定及事件綁定,比如ng-repeat

compilelink的形式

compile

  • function compile(element, attrs, transclude) { ... }
  • 在compile階段要執行的函數,返回的function就是link時要執行的function
  • 常用參數爲elementattrs,分別是dom元素和元素上的屬性們,其它的以後細說
  • 較少使用,因爲大部分directive是處理dom元素的行爲綁定,而不是改變它們

link

  • function link(scope, element, attrs, controller) { ... }
  • 在link階段要執行的函數,這個屬性只有當compile屬性沒有設置時才生效
  • 常用參數爲scopeelementattrs,分別是當前元素所在的scope,dom元素和元素上的屬性們,其它的以後細說
  • directive基本上都會有此函數,可以註冊事件,並與scope相綁

compilelink的使用時機

compile

  • 想在dom渲染前對它進行變形,並且不需要scope參數
  • 想在所有相同directive裏共享某些方法,這時應該定義在compile裏,性能會比較好
  • 返回值就是link的function,這時就是共同使用的時候

link

  • 對特定的元素註冊事件
  • 需要用到scope參數來實現dom元素的一些行爲

 

11、作用域和控制器 

控制器是通過增強作用域來提供業務邏輯的代碼。這是我們在作用域這個角度爲它下的一個定義。註冊的控制器在

ng-controller指令連接到AngularJS模板時被實例化的。每個控制器都會有一個自己的單獨的子作用域,至於在自定

義指令中的$scope,是與控制器作用域同級的,和控制器作用域並沒有任何的隸屬關係。

 

12、作用域和模板 

模板是用來爲Angular提供視圖的。在模板中定義AngularJS指令時,可以使用作用域屬性和函數。在模板的表達式中

也可以引用作用域中的屬性。

 

13、作用域生命週期 

創建->監視器註冊->模型變化->變化觀察->作用域銷燬

創建階段發生在作用域初始化時。啓動應用時將創建一個根作用域,當遇到ng-controller或者ng-repeat指令時,控制

器或者指令鏈接到模板時,將會創建子作用域。在創建階段,將會創建一個digest循環,用於與瀏覽器時間循環交

互。該digest循環負責使用模型的變化更新DOM元素,並執行所有已經註冊的監視器函數。如果需要手動的執行dig

est循環,可以通過執行$digest()方法實現. 例如,下面的代碼將執行所有的異步改動,然後執行作用域中的監視函

數。

 

 

$scope.$digest()

 

我們可以用$watch()方法在作用域上註冊自己的監視函數。該方法接受兩個參數,一個是作用域屬性的名字,一個

是回調函數。

$scope.$watch('name', function(newValue, oldValue) {

});

3.作用域層次問題 

這裏有一個來自《Angular Js開發祕籍》的Demo,簡單明瞭。

scopeDemo.js

angular.module('myApp',[])
.controller('LevelA', function($scope){
    $scope.title = "LevelA";
    $scope.valueA = 1;
    $scope.inc = function(){
        $scope.valueA++;
    };
})
.controller('LevelB', function($scope){
    $scope.title = "LevelB";
    $scope.valueB = 1;
    $scope.inc = function(){
        $scope.valueB++;
    };
})
.controller('LevelC', function($scope){
    $scope.title = "LevelC";
    $scope.valueC = 1;
    $scope.inc = function(){
        $scope.valueC++;
    };
});


HTML:

 

<!doctype html>
<html ng-app="myApp">
<head>
  <title>AngularJS Scope</title>
</head>
<body>
  <div ng-controller="LevelA">
    <h3>{{h3}}</h3>
    ValueA = {{valueA}}<input type="button" ng-click="inc()" value="+" />
    <div ng-controller="LevelB"><hr>
      <h3>{{title}}</h3>
      ValueA = {{valueA}}<br>
      ValueB = {{valueB}}<br>
      <input type="button" ng-click="inc()" value="+" />
      <div ng-controller="LevelC"><hr>
        <h3>{{title}}</h3>
        ValueA = {{valueA}}<br>
        ValueB = {{valueB}}<br>
        ValueC = {{valueC}}
        <input type="button" ng-click="inc()" value="+" />
      </div>
    </div>
  </div>
  <script src="js/angular.min.js"></script>
  <script src="scopeDemo.js"></script>
</body>
</html>

 

 

14、在debugger中查看scope:

(1). 在瀏覽器中,對着感興趣的元素點擊右鍵,選擇“查看元素”。我們可以看到瀏覽器debugger高亮了我們選中的元素。

(2). debugger允許我們在console中通過$0變量去訪問當前選擇的元素。

(3). 想查看關聯的scope,我們可以在console中輸入:angular.element($0).scope()

 

15、$on、$emit和$broadcast的使用

  • $emit只能向parent controller傳遞event與data
  • $broadcast只能向child controller傳遞event與data
  • $on用於接收event與data

在一個controller裏面通過事件觸發一個方法,在方法裏面通過$broadcast或$emit來定義一個變量,在父,子controller裏面通過$on來獲取。

 

 

parent用$broadcast賦的值,只能子級得到值;$emit賦的值,只能父級得到;而平級的什麼都不能得到。

例子:

 

<!DOCTYPE HTML>
<html lang="zh-cn" ng-app = "myApp">
<head>
  <meta charset="UTF-8">
  <title>scope-event-propagation</title>
  <style type="text/css">
    .ng-cloak {
      display: none;
    }
    .ng-scope {
      border: 1px dashed red;
    }
  </style>
</head>
<body class="ng-cloak">
  <div ng-controller="MyController">
    root scope count:{{count}}
    <ul>
      <li ng-repeat="i in [1]" ng-controller="MyController">
        <button ng-click="$emit('MyEvent')">$emit("MyEvent")</button>
        <button ng-click="$broadcast('MyEvent')">$broadcast("MyEvent")</button>
        <br/>
        middle scope count:{{count}} //平級
        <ul>
          <li ng-repeat="item in [1,2]" ng-controller="MyController">
            Leaf scope count:{{count}}
          </li>
        </ul>
      </li>
    </ul>
  </div>
</body>
<script src = "js/angular.min.js"></script>
<script src="demo.js">
</script>
</html>

 

demo.js

angular.module('myApp', [])
.controller("MyController", function ($scope) {
	$scope.count = 0;
	$scope.$on("MyEvent", function() {
		$scope.count++;
	});
})

 

 

16、我們通過使用angular.element(aDomElement).scope()查看任意DOM元素的scope。

 

17、模塊定義

 

angular.module("app", []);
      angular.module("app").controller("testCtrl", ["$scope", function ($scope) {
          $scope.currentMenu = "menu1";
          $scope.selectMenu = function (menu) {
              $scope.currentMenu = menu;
          }
      }]);

 

  • 我給ng-app指定了一個名稱叫”app“,同時js代碼使用angular.module("app", []);定義了一個名稱爲”app“的module,同時用這個app module 的controller方法定義了一個testCtrl;定義module函數是angular對象上的靜態方法,第一個參數傳名稱,第二個參數是一個數組,這個數組表示這個module所引用的其他module,在這個例子中我們沒有使用任何其他的module,所以傳入一個空的數組,如果第二個參數不傳,表示獲取名稱爲”app“的module

 

 

發佈了852 篇原創文章 · 獲贊 1848 · 訪問量 137萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章