angular(常識) AngularJS的學習 $on、$emit和$broadcast的使用

 

我以爲angularjs是前端框架,而jquery只是前端工具,這兩個仍是沒有可比性的。javascript

看知乎上關於jquery和angular的對比http://www.zhihu.com/question/27471743php

優勢:1. 模板功能強大豐富,而且是聲明式的,自帶了豐富的Angular指令;2. 是一個比較完善的前端MV*框架,包含模板,數據雙向綁定,路由,模塊化,服務,過濾器,依賴注入等全部功能;3. 自定義Directive,比jQuery插件還靈活,可是須要深刻了解Directive的一些特性,簡單的封裝容易,複雜一點官方沒有提供詳細的介紹文檔,咱們能夠經過閱讀源代碼來找到某些咱們須要的東西,如:在directive使用 $parse;4. ng模塊化比較大膽的引入了Java的一些東西(依賴注入),可以很容易的寫出可複用的代碼,對於敏捷開發的團隊來講很是有幫助,咱們的項目從上線到目前,UI變化很大,在摸索中迭代產品,可是js的代碼基本上不多改動。5. 補充:Angular支持單元測試和e2e-testing。缺點:1. 驗證功能錯誤信息顯示比較薄弱,須要寫不少模板標籤,沒有jQuery Validate方便,因此咱們本身封裝了驗證的錯誤信息提示,詳細參考 why520crazy/w5c-validator-angular · GitHub ;2. ngView只能有一個,不能嵌套多個視圖,雖然有 angular-ui/ui-router · GitHub 解決,可是貌似ui-router 對於URL的控制不是很靈活,必須是嵌套式的(也許我沒有深刻了解或者新版本有改進);3. 對於特別複雜的應用場景,貌似性能有點問題,特別是在Windows下使用chrome瀏覽器,不知道是內存泄漏了仍是什麼其餘問題,沒有找到好的解決方案,奇怪的是在IE10下反而很快,對此還在觀察中;4. 此次從1.0.X升級到1.2.X,貌似有比較大的調整,沒有完美兼容低版本,升級以後可能會致使一個兼容性的BUG,具體詳細信息參考官方文檔 AngularJS ,對應的中文版本:Angular 1.0到1.2 遷移指南5. ng提倡在控制器裏面不要有操做DOM的代碼,對於一些jQuery 插件的使用,若是想不破壞代碼的整潔性,須要寫一些directive去封裝插件,可是如今有不少插件的版本已經支持Angular了,如:jQuery File Upload Demo6. Angular 太笨重了,沒有讓用戶選擇一個輕量級的版本,固然1.2.X後,Angular也在作一些更改,好比把route,animate等模塊獨立出去,讓用戶本身去選擇。固然使用的人多才會暴露更多的問題,一塊兒爲這些問題尋找解決方案是一個社區的良性趨勢,選擇Angular,的確使咱們的開發效率大大提升。html

2009年google feedback project 1500行
爲了解決ajax開發的痛苦前端

1. 幾個經常使用的概念
a.客戶端模板:模板和數據都會發送到瀏覽器中
b.mvc:
c.數據綁定:自動將Model和view間的數據同步。
angular 實現數據綁定的方式,可讓咱們把model當作程序中惟一可信的數據來源。view始終是model的投影。。當model發生變化時,會自動反映到view上。
大多數的數據綁定都是單向的,當咱們的model和view修改後要去提醒另一個的話,就必須使用ajax之類的,好比jquery還要手動的同步,這樣子的話,增長了沒必要要的麻煩。
d.依賴注入:java

2.依賴注入 的詳解node

回顧下spring中的ioc 控制反轉:jquery

控制反轉(Inversion of Control,英文縮寫爲IoC)是一個重要的面向對象編程的法則來削減計算機程序的耦合問題,也是輕量級的Spring框架的核心。 控制反轉通常分爲兩種類型,依賴注入(Dependency Injection,簡稱DI)和依賴查找(Dependency Lookup)。依賴注入應用比較普遍。git

我的理解:就是原本須要你在程序設計時,建立的某些對象,交給spring來管理,當你須要某個時候須要某個對象的時候spring在給你,這樣子對象的生命週期之類的就由spring來維護了。angularjs

js的依賴注入:(咱們這裏所說的依賴注入和上面的ioc或者di仍是有點不一樣的,咱們這裏更侷限在依賴這個詞)
方法1:

var A = function () {
   this.getName = function () {
   return '張三';
 }
}github

var B = function (obj) {
// B 依賴於 a
document.write(obj.getName());
}

// a 注入 ba

var a = new A;
var b = new B(a);

========================

方法2:

var A = function () {
   this.getName = function () {
   return '張三';
 }
}

var a = new A;

var B = function () {
// B 依賴於 a
document.write(a.getName());
}

// a 注入 ba


var b = new B(a);

===========================

3. 在 ng-app下

<input type="text" ng-model="name" value=""/>

<!--angular的表達式-->
{{ name }}

<input type="text" ng-model="name" value=""/>

這三個name的數據是綁定。

4. 控制器

<div ng-controller="firstController">
    <input type="text" value="" ng-model="name"/>
    <input type="text" value="" ng-model="age"/>
    {{name}}
    {{age}}
</div>

var firstController = function($scope){

      // $scope 咱們叫作做用域
      // 申明一個Model
      $scope.name = '張三';

     $scope.age = 20;

}

5. 多個控制器

<div ng-controller="firstController">
   <input type="text" value="" ng-model="name"/>

   <div ng-controller="secondController">
   <input type="text" value="" ng-model="name"/>
    </div>
</div>

var firstController = function($scope){

$scope.name = '張三';
console.log($scope);

}

var secondController = function($scope){

console.log($scope);
}

6. $apply方法

var firstController = function($scope){

    $scope.date = new Date();

    // setInterval(function(){
    // // 這裏雖然變 可是並無觸發 髒檢查
    // $scope.date = new Date();
   //
   // },1000)

   setInterval(function(){
          $scope.$apply(function(){
              $scope.date = new Date();
              //....會去觸發髒檢查
         })
  },1000)


   // 觸發一次髒檢查
}

7. watch

var firstController = function($scope){

    $scope.name = '張三';
    $scope.data = {
        name :'李四',
        count:20
    }
   $scope.count = 0;

   // 監聽一個model 當一個model每次改變時 都會觸發第2個函數
   $scope.$watch('name',function(newValue,oldValue){

      ++$scope.count;

      if($scope.count > 30){
         $scope.name = '已經大於30次了';
     }
  });


    $scope.$watch('data',function(){

    },true)

  // 上面的true表示只要有一個true發生改變,那麼這個watch就觸發。
}

8. 一個簡單的互動的demo代碼

 1  <div ng-controller="cartController" class="container">
 2         <table class="table" ng-show="cart.length">
 3             <thead>
 4                 <tr>
 5                     <th>產品編號</th>
 6                     <th>產品名字</th>
 7                     <th>購買數量</th>
 8                     <th>產品單價</th>
 9                     <th>產品總價</th>
10                     <th>操做</th>
11                 </tr>
12             </thead>
13             <tbody>
14                 <tr ng-repeat="item in cart">
15                     <td>{{item.id}}</td>
16                     <td>{{item.name}}</td>
17                     <td>
18                         <button type="button" ng-click="reduce(item.id)" class="btn tn-primary">-</button>
19                         <input type="text" value="{{item.quantity}}" ng-model="item.quantity" >
20                         <button type="button" ng-click="add(item.id)" class="btn tn-primary">+</button>
21                     </td>
22                     <td>{{item.price}}</td>
23                     <td>{{item.price * item.quantity}}</td>
24                     <td>
25                         <button type="button" ng-click="remove(item.id)" class="btn btn-danger">移除</button>
26                     </td>
27                 </tr>
28                 <tr>
29                     <td>
30                         總購買價
31                     </td>
32                     <td>
33                         {{totalPrice()}}
34                     </td>
35                     <td>
36                         總購買數量
37                     </td>
38                     <td>
39                         {{totalQuantity()}}
40                     </td>
41                     <td colspan="2">
42                         <button type="button" ng-click="cart = {}" class="btn btn-danger">清空購物車</button>
43                     </td>
44                 </tr>
45             </tbody>
46         </table>
47 
48         <p ng-show="!cart.length">您的購物車爲空</p>
49     </div>

 

  1 var cartController = function ($scope) {
  2 
  3     $scope.cart = [
  4         {
  5             id: 1000,
  6             name: 'iphone5s',
  7             quantity: 3,
  8             price: 4300
  9         },
 10         {
 11             id: 3300,
 12             name: 'iphone5',
 13             quantity: 30,
 14             price: 3300
 15         },
 16         {
 17             id: 232,
 18             name: 'imac',
 19             quantity: 4,
 20             price: 23000
 21         },
 22         {
 23             id: 1400,
 24             name: 'ipad',
 25             quantity: 5,
 26             price: 6900
 27         }
 28     ];
 29 
 30 
 31     /**
 32      * 計算購物總價
 33      */
 34     $scope.totalPrice = function () {
 35         var total = 0;
 36         angular.forEach($scope.cart, function (item) {
 37             total += item.quantity * item.price;
 38         })
 39         return total;
 40     }
 41 
 42     /**
 43      * 計算總購買數
 44      */
 45     $scope.totalQuantity = function () {
 46         var total = 0;
 47         angular.forEach($scope.cart, function (item) {
 48             total += parseInt(item.quantity);
 49         })
 50         return total;
 51     }
 52 
 53 
 54     /**
 55      * 找一個元素的索引
 56      */
 57     var findIndex = function (id) {
 58         var index = -1;
 59 
 60         angular.forEach($scope.cart, function (item, key) {
 61             if (item.id === id) {
 62                 index = key;
 63                 return;
 64             }
 65         });
 66 
 67         return index;
 68     }
 69 
 70 
 71     /**
 72      * 爲某個產品添加一個數量
 73      */
 74     $scope.add = function (id) {
 75         var index = findIndex(id);
 76 
 77         if (index !== -1) {
 78             ++$scope.cart[index].quantity;
 79         }
 80     }
 81 
 82 
 83     /**
 84      * 爲某個產品減小一個數量
 85      */
 86     $scope.reduce = function (id) {
 87         var index = findIndex(id);
 88 
 89         if (index !== -1) {
 90             var item = $scope.cart[index];
 91             if(item.quantity > 1){
 92                 --item.quantity;
 93             }else{
 94                 var returnKey = confirm('是否從購物車內刪除該產品!');
 95                 if(returnKey){
 96                     $scope.remove(id);
 97                 }
 98             }
 99 
100         }
101     }
102 
103     /**
104      * 移除一項
105      */
106     $scope.remove = function (id) {
107 
108 
109         var index = findIndex(id);
110         // 若是找到了那個item
111         if (index !== -1) {
112             $scope.cart.splice(index, 1);
113         }
114 
115         // 自動作髒檢查
116     }
117 
118     // 監聽數量 若是小於 1 則讓用戶判斷是否要刪除產品
119     $scope.$watch('cart',function(newValue,oldValue){
120 
121         angular.forEach(newValue,function(item,key){
122             if(item.quantity < 1){
123                 var returnKey = confirm('是否從購物車內刪除該產品!');
124                 if(returnKey){
125                     $scope.remove(item.id);
126                 }else{
127                     item.quantity = oldValue[key].quantity;
128                 }
129             }
130         })
131     },true);
    //若是這個方式和上邊的reduce同時執行的話,特別是reduce爲0的時候, 先執行reduce方法,remove以後,執行這個函數的時候,就已經找不到那個cart中對應的值了,因此confirm不會重複彈出。
132 133 134 135 }

9. 控制器屬於模塊    。

模塊是組織業務的一個框架,在一個模塊當中定義多個服務。當引入了一個模塊的時候,就可使用這個模塊提供的一種或多種服務了。
angularjs自己的一個默認模塊叫作ng,它提供了$http,$scope等等服務。
服務只是模塊提供的多種機制中的一種,其餘的而還有指令(directive),
過濾器(filter),及其餘配置信心。
也能夠在已有的模塊中新定義一個服務,也能夠先定義一個模塊,而後在新模塊中定義新服務,。
服務是須要顯示的聲明依賴引入關係的,讓ng自動地作注入。

<div ng-app="myApp">

        <div ng-controller="firstController">
            {{name}}
        </div>

    </div>
var myApp = angular.module('myApp',[]);


myApp.controller('firstController',function($scope){
    $scope.name = '張三';
});

10.  

$provide.service() 必須返回對象(數組也是對象),不能返回字符串之類的。
$provide.factory 這個能夠返回任何類型。

var myApp = angular.module('myApp',[],function($provide){

    // 自定義服務
    $provide.provider('CustomService',function(){

        this.$get = function(){
            return {
                message : 'CustomService Message'
            }
        }
    });

    // 自定義工廠
    $provide.factory('CustomFactory',function(){
        return [1,2,3,4,5,6,7];
    });

    // 自定義服務
    $provide.service('CustomService2',function(){
        return 'aaa';
    })

});

myApp.controller('firstController',function($scope,CustomFactory,CustomService2){
    $scope.name = '張三';

    console.log(CustomFactory);

    console.log(CustomService2);

});

//myApp.service();
//myApp.factory();

11. 

服務自己是一個任意的對象。
ng提供服務的過程涉及它的依賴注入機制。
angular 是用$provider對象來實現自動依賴注入機制,注入機制經過調用一個provider的$get方法,
把獲得對象做爲參數進行相關調用。
$provider.provider是一種定義服務的方法,$provider還提供了不少不少簡便的方法,這些方法還被module所引用。
也許這裏有人問:control層和service層的區別:
1.事務的回滾在service層,好比重定向之類的在control層。
view層:    結合control層,顯示前臺頁面。
 
  
control層:業務模塊流程控制,調用service層接口。
 
  
service層:業務操做實現類,調用dao層接口。
 
  
dao層:     數據業務處理,持久化操做
 
  
model層: pojo,OR maping,持久層
 
 
var myApp = angular.module('myApp',[],function($provide){


    // 自定義服務
  //自定義服務自己就是一個服務,這個服務的數據能夠設置也能夠返回,而service和factoyr只能返回數據。
$provide.provider('CustomService',function(){ this.$get = function(){ return { message : 'CustomService Message' } } }); $provide.provider('CustomService2',function(){ this.$get = function(){ return { message : 'CustomService2 Message' } } }); }); myApp.controller('firstController',function(CustomService,$scope,CustomService2){ $scope.name = '張三'; console.log(CustomService2); });

12. 多個控制器數據的共享兩種方法:

$scope.data = $scope.$$prevSibling.data; 這樣子必須是一個對象的值,在html頁面的顯示,必須是一個data.name這種形式,若是是data的話那麼就不行。
<div ng-app="myApp">


        <div ng-controller="firstController">
            first.data <input type="text" ng-model="data.name" />
            first.Data <input type="text" ng-model="Data.message" />
            <p>
                first-name:{{data.name}}
            </p>
            <p>
                first-message:{{Data.message}}
            </p>
        </div>

        <div ng-controller="secondController">
            <p>
                second-name:{{data.name}}
            </p>
            <p>
                second-message:{{Data.message}}
            </p>
        </div>
    </div>
angular.module('myApp',[])

.factory('Data',function(){
    // this.$get = function(){}
    return {
        message : '共享的數據'
    };
})

.controller('firstController',function($scope,Data){
   $scope.data  = {
       name : '張三'
   };

   $scope.Data = Data;
})

.controller('secondController',function($scope,Data){
   $scope.data = $scope.$$prevSibling.data;

   $scope.Data = Data;
});

13. 過濾器:

angular.module('myApp',[])

.factory('Data',function(){

    return {
        message : '共享的數據'
    };
})

.controller('firstController',function($scope,Data,$filter){
   $scope.data = Data;

   $scope.today = new Date;

})
<div ng-controller="firstController">

        <!--123,456,789-->
        <p>{{123456789 | number}}</p>
        <!--12,345.679-->
        <p>{{12345.6789 | number:3}}</p>

        <!--$999,999.00-->
        <p>{{999999 | currency}}</p>
        <!--rmb999,999.00-->
        <p>{{999999 | currency:'rmb'}}</p>

        <p>
            default:{{ today }}
        </p>

        <p>
            medium: {{ today | date:'medium'}}
        </p>

        <p>
            short:{{ today | date:'short'}}
        </p>

        <p>
            fullDate:{{ today | date:'fullDate'}}
        </p>

        <p>
            longDate:{{ today | date:'longDate'}}
        </p>

        <p>
            mediumDate:{{ today | date:'mediumDate'}}
        </p>

        <p>

            shortDate:{{ today | date:'shortDate'}}
        </p>

        <p>
            mediumTime:{{ today | date:'mediumTime'}}
        </p>

        <p>
            shortTime:{{ today | date:'shortTime'}}
        </p>

        <p>
            year:
            {{today | date : 'y'}}
            {{today | date : 'yy'}}
            {{today | date : 'yyyy'}}
        </p>
        <p>
            month:
            {{today | date : 'M'}}
            {{today | date : 'MM'}}
            {{today | date : 'MMM'}}
            {{today | date : 'MMMM'}}
        </p>
        <p>
            day:
            {{today | date : 'd'}}
            Day in month {{today | date : 'dd'}}
            Day in week {{today | date : 'EEEE'}}
            {{today | date : 'EEE'}}
        </p>

        <p>
            hour:
            {{today | date : 'HH'}}
            {{today | date : 'H'}}
            {{today | date : 'hh'}}
            {{today | date : 'h'}}
        </p>

        <p>
            minute:
            {{today | date : 'mm'}}
            {{today | date : 'm'}}
        </p>

        <p>
            second:
            {{today | date : 'ss'}}
            {{today | date : 's'}}
            {{today | date : '.sss'}}
        </p>

        <p>
            {{today | date : 'y-MM-d H:m:s'}}
        </p>


</div>

14. 更多的選擇器:

原始數據類型:

 

 <div ng-controller="firstController">

        <!--[1,2,3,4,5]-->
        <p>{{[1,2,3,4,5,6,7] | limitTo:5}}</p>

        <!--[3,4,5,6,7]-->
        <p>{{[1,2,3,4,5,6,7] | limitTo:-5}}</p>

        <!-- hello world -->
        <p>{{data.message | lowercase}}</p>
        <!-- HELLO WORLD -->
        <p>{{data.message | uppercase}}</p>

        <p>
            <!-- [{"name":"上海11212","py":"shanghai"}]-->
            {{ data.city | filter : '上海'}}
        </p>
        <p>
            <!-- []-->
            {{ data.city | filter : 'name'}}
        </p>

        <p>
            <!-- name":"上海11212","py":"shanghai"},{"name":"北京","py":"beijing"}-->
            {{ data.city | filter : {py:'g'} }}
        </p>

        <p>
            <!-- name":"上海11212","py":"shanghai"},{"name":"北京","py":"beijing"}-->
            {{ data.city | filter : checkName }}
        </p>

        <p>
            <!-- [{"name":"北京","py":"beijing"},{"name":"上海11212","py":"shanghai"},{"name":"四川","py":"sichuan"}] -->
            <!-- 默認順序是 正序 asc a~z -->
            {{ data.city | orderBy : 'py'}}

            <!-- 默認順序是 反序 desc z~a  -->
            <!-- [{"name":"四川","py":"sichuan"},{"name":"上海11212","py":"shanghai"},{"name":"北京","py":"beijing"}] -->
            {{ data.city | orderBy : '-py'}}
        </p>
angular.module('myApp',[])

.factory('Data',function(){

    return {
        message : 'Hello World',
        city : [
            {
                name:'上海11212',
                py : 'shanghai'
            },
            {
                name:'北京',
                py : 'beijing'
            },
            {
                name:'四川',
                py : 'sichuan'
            }
        ]
    };
})

.controller('firstController',function($scope,Data,$filter){
   $scope.data = Data;

   $scope.today = new Date;


   // 過濾器
   var number = $filter('number')(3000);

   var jsonString = $filter('json')($scope.data);

        console.log(jsonString);
        console.log($scope.data);

   $scope.checkName = function(obj){
        if(obj.py.indexOf('h') === -1)
            return false;
        return true;
   }

})

15. 自定義的過濾器

<div ng-controller="firstController">
        <ul>
            <li ng-repeat="user in data | filterAge">
                {{user.name}}
                {{user.age}}
                {{user.city}}
            </li>
        </ul>
    </div>
var myApp = angular.module('myApp', [], function ($filterProvider, $provide, $controllerProvider) {

    $provide.service('Data', function () {
        return [
            {
                name: '張三',
                age: '20',
                city: '上海'
            },
            {
                name: '李四',
                age: '30',
                city: '北京'
            }
        ];

    });

    $filterProvider.register('filterAge', function () {
        return function (obj) {
            var newObj = [];

            angular.forEach(obj, function (o) {
                if (o.age > 20) {
                    newObj.push(o);
                }
            });

            return newObj;

        }
    });


    $controllerProvider.register('firstController', function ($scope, Data) {
        $scope.data = Data;
    })



})

// module.filter
.filter('filterCity',function(){
    return function(obj){
        var newObj = [];

        angular.forEach(obj, function (o) {
            if (o.city === '上海') {
                newObj.push(o);
            }
        });

        return newObj;
    }
})

 

16.正確的使用controller

正確的使用controller
controller不該該嘗試作太多的事情。它應該僅僅包含單個視圖所須要的業務邏輯,保持controller的簡單性,常見辦法是抽出不屬於controller的工做到service中,在controller經過依賴注入來使用service。
不要在controller中作如下的事情:
1.任何類型的DOM操做-controller應該僅僅包含業務邏輯,任何表現邏輯放到controller中,大大地影響了應用邏輯的可測試性。angular爲了自動操做(更新)DOWM,提供的數據綁定。若是但願執行咱們自定義的DOM操做,能夠把表現邏輯抽取到directive中。
2.input formatting(輸入格式化) 使用angular form controls代替。
3.output filtering(輸出格式化過濾) 使用angular filters.
4.執行無狀態或有狀態的,controller共享的代碼--使用angular services代替。
5. 實例化或者管理其餘組件的生命週期。(例如建立一個服務實例)

17.代碼的顯示注入和隱式注入

var myApp = angular.module('myApp', [], ['$filterProvider', '$provide', '$controllerProvider', function (a, b, c) {
    console.log(a, b, c);
}])

.
factory('CustomService', ['$window', function (a) {
    console.log(a);
}])

// 隱示的依賴注入
    .controller('firstController', function ($scope, CustomService) {
        console.log(CustomService);
    })

// 顯示的依賴注入
    .controller('secondController', ['$scope', '$filter', function (a, b) {
        console.log(b('json')([1, 2, 3, 4, 5]));
    }]);

function otherController(a) {
    console.log(a);
}

otherController.$inject = ['$scope'];

 18. 內置指令:

渲染指令:
ng-init
ng-bind
ng-repeat
$index 當前索引
$first 是否爲頭元素
$middle 是否爲非頭非尾元素
$lasth是否爲尾元素

ng-include
ng-bing-template.

ng-bind
ng:bind
data-ng-bind
x-ng-bind
事件指令:
ng-change
ng-click
ng-dblclick
ng-mousedown
ng-mouseenter
ng-mouseleave
ng-mousemove
ng-mouseover
ng-mouseup
ng-submit
節點指令
ng-style
ng-class
ng-class-even
ng-class-odd

這裏的red表示style中的類,而-even表示在偶數列會添加這個class.

 

ng-show
ng-hide
ng-switch
ng-src
ng-href
ng-if

==

.red{color:red;}
ng-class='{red:status}'

 

什麼是指令:
能夠利用指令來擴展HTML標籤,增長聲明式語法來實現想作的任何事,能夠對應用有特殊意義的元素和屬性來替換通常的HTML標籤。
angular 也內置了很是堵偶的指令,ng-app ,ng-controller.

ngsrc 延遲加載。等angular加載完而後加載。這個屬性。

<div ng-app="myApp">

    <div ng-controller="firstController">
        <p>{{1+1}}</p>
        <p ng-bind="1+1">2</p>
        <p ng-bind-template="{{1+1}}"></p>

        <!-- $scope.cityArr = ['上海','北京','杭州'] -->
        <ul ng-class="{red:status}" ng-init="cityArr = ['上海','北京','杭州']">
            <li ng-class-even="'偶數'" ng-class-odd="'奇數'" ng-repeat="city in cityArr" >
            <span>
                index:{{$index}}
            </span>
            <span>
                first:{{$first}}
            </span>
            <span>
                middle:{{$middle}}
            </span>
            <span>
                last :{{$last}}
            </span>
            <span>
                {{city}}
            </span>
            </li>
        </ul>



        <div ng-include="'other.html'">

        </div>

        <div ng-include src="'other.html'">

        </div>


















    </div>
</div>

var myApp = angular.module('myApp', [])

    .controller('firstController', function ($scope) {
        $scope.status = false;

        $scope.changeStatus = function (event) {
            // 經過element轉換成 jquery對象
            angular.element(event.target).html('切換狀態爲:' + $scope.status);

            $scope.status = !$scope.status;

        }

        $scope.defaultStyle = {
            color: 'red',
            'margin-top': '50px'
        };

        $scope.src = 'http://www.angularjs.org/img/AngularJS-large.png';
    })

 $scope.changeStatus 這個會自動觸發髒檢查。

ng-style="{color:'red','margin-top':'50px'}" 後邊這個注意加單引號。

 19. 自定義的指令:

自定義過濾器,factory,service.

templateUrl:加載模板所要使用的URl
可加載當前模板對應的text/ng-template script id

在使用chrome瀏覽器時,‘同源策略’會阻止chrome從file://中加載模板,並顯示一個"Acces-Control-Allow-Origin"不容許源爲null,能夠把項目放在服務器上加載,命令爲:chrome -allow-file-access-from-files

<div ng-app="myApp">

    <custom-tags>1212</custom-tags>

    <div class="custom-tags">

    </div>

    <div custom-tags>

    </div>

    <!-- directive:custom-tags -->
</div>
var myApp = angular.module('myApp', [], ['$compileProvider',function ($compileProvider) {

    $compileProvider.directive('customTags',function(){
        return {
            restrict:'ECAM',
            template:'<div>custom-tags-html</div>',
            replace:true  //這個屬性對於E這種指令適用,能夠提現出來
        }
    });

}])

//.directive('')  這是一種簡單的寫法

20.transclude:true保留原始數據

21.優先級(不是很重要) 


priority && terminal

priority 設置指令在模板中的執行順序,順序是相對於元素上其餘執行而言,默認爲0,從大到小的順序依次執行。

設置優先級的狀況比較少,象ng-repest,在遍歷元素的過程當中,須要angular先拷貝生成的模板元素,在應用其餘指令,因此ng-repeat默認的priority是1000

terminal是否當前指令的權重爲結束界限,若是這值設置爲true,則節點中權重小於當前指令的其餘指令不會被執行。相同權重的會執行。

22.

angularjs指令編譯三階段
1.標準瀏覽器API轉化。
將html轉化成dom,因此自定義的html標籤必須符合html的格式。
2.angular compile
搜索匹配directive,按照priority排序,並執行directive上的compile方法。
3.angular link
執行directive上的link方法,進行scope綁定及事件綁定。

directive能夠配置的指令:
priority
template
terminal
templateUrl
scope
replace: 是否替換當前html標籤
controller
transclude
controllerAs
compile
require
link
restrict

23.

compile

compile:function(tElement,eAttrs,transclude)
compile函數用來對模板自身進行轉換,僅僅在編譯階段運行一次,
compile中直接返回的函數是postLink,表示參數須要執行的函數,也能夠返回一個對象裏邊包含preLink和postLink,
當定義compile參數時,將無視link參數,由於compile裏返回的就是該指令須要執行的link函數。

24.

一個標籤有兩個指令的話,最好有一個template(多的狀況不經常使用)
compile返回的就是link函數,因此說定義了compile就不用定義link.
compile的三個參數,(tElement,eAttrs,transclude)
eElement是angular內置的jquery的一個對象因此能夠調用eElement.append的方法。
compile 和link的使用時機
compile想再dom渲染前對它進行變形,而且不須要scope參數想在全部相同directive裏共享某些方法,這時應該定義compile裏,性能會比較好,返回值就是link的function,這時就是共同使用的時候。
link 對特定的元素註冊事件。
須要用到scope參數來實現dom元素的一些行爲。
若是在你的directive的返回不是一個對象,而是返回的是一個匿名方法的話,這個方法就是postLink方法。或者說就是Link,link就是postLink。

link(scope,iElement,iAttrs, controller)
link參數表明的是compile返回的postLink
preLink表示在編譯階段以後,指令練級到子元素以前運行。
postLink 表示會在全部子元素指令都鏈接以後才運行
link函數負責在模型和視圖之間進行動態關聯,對於每一個指令的每一個實例,link函數都會執行一次。

25.

<div ng-app="myApp">

    <div ng-controller="firstController">
        <!--
            1. div 轉換爲dom結構
            2. 默認的優先級爲0,哪一個先定義哪一個先使用

        -->
        <div ng-repeat="user in users" custom-tags="" custom-tags2>

        </div>

    </div>



</div>
var i = 0;

var myApp = angular.module('myApp', [])

    .directive('customTags',function(){
        return {
            restrict : 'ECAM',
            template : '<div>{{user.name}}</div>',
            replace : true,
            compile:function(tElement,tAttrs,transclude){

                tElement.append(angular.element('<div>{{user.name}}{{user.count}}</div>'));

                // 編譯階段...
                console.log('customTags compile 編譯階段...');

                return {
                    // 表示在編譯階段以後,指令鏈接到子元素以前運行
                    pre:function preLink(scope,iElement,iAttrs,controller){
                        console.log('customTags preLink..')
                    },
                    // 表示在全部子元素指令都鏈接以後才運行
                    post:function postLink(scope,iElement,iAttrs,controller){

                        iElement.on('click',function(){
                            scope.$apply(function(){
                                scope.user.name = 'click after';
                                scope.user.count = ++i;
                                // 進行一次 髒檢查
                            });
                        })

                        console.log('customTags all child directive link..')
                    }
                }
                // 能夠直接返回 postLink
                // return postLink function(){
                    // console.log('compile return fun');
                //}
            },
            // 此link表示的就是 postLink
            link:function(){
//                iElement.on('click',function(){
//                    scope.$apply(function(){
//                        scope.user.name = 'click after';
//                        scope.user.count = ++i;
//                        // 進行一次 髒檢查
//                    });
//                })
            }
        }
    })

    .directive('customTags2',function(){
        return {
            restrict : 'ECAM',
            replace : true,
            compile:function(){
                // 編譯階段...
                console.log('customTags2 compile 編譯階段...');

                return {
                    // 表示在編譯階段以後,指令鏈接到子元素以前運行
                    pre:function preLink(){
                        console.log('customTags2 preLink..')
                    },
                    // 表示在全部子元素指令都鏈接以後才運行
                    post:function postLink(){
                        console.log('customTags2 all child directive link..')
                    }
                }

            }
        }
    })


    .directive('customTags3',function(){

       // return postLink;
       return function(){

       }
    })

    .controller('firstController', ['$scope', function ($scope) {
        $scope.users = [
            {
                id:10,
                name:'張三'
            },
            {
                id:20,
                name:'李四'
            }
        ];
    }]);

 26.

controller && controllerAds && require
controller他會暴露一個API,利用這個API能夠在多個指令之間經過依賴注入進行通訊
controller($scope,$element,$transclude)
controllerAs是給controller起個別名,方便使用
require能夠將其餘指令傳遞給本身
directiveName: 經過駝峯法的命名指定了控制器應該帶有哪一條指令,默認會從同一個元素上的指令
^directiveName: 在父級朝找指令
?directiveName:表示指令是可選的,若是找不到,不須要拋出移除。

27.自定義指令:controllerAs 和link,可使用上面的controller中的屬性方法

 
 
angular.module('myApp', [])

    .directive('bookList', function () {
        return {
            restrict: 'ECAM',
            controller: function ($scope) {
                $scope.books = [
                    {
                        name: 'php'
                    },
                    {
                        name: 'javascript'
                    },
                    {
                        name: 'java'
                    }
                ];
                $scope.addBook = function(){

                }
                this.addBook = function(){
                    // ...
                }
            },
            controllerAs:'bookListController',//上邊 controller的別名,下邊的link或者compile可使用
            template: '<ul><li ng-repeat="book in books">{{book.name}}</li></ul>',
            replace:true,
            link:function(scope,iEelement,iAttrs,bookListController){
          //上邊的iEelement表示的是template中的內容和jquery中的同樣,bookListController表示的上邊的controllerAs,
          // 若是調用this.addBook,你直接用
bookListController.addBook,若是調$scope.addBook

          iEelement.on('click',bookListController.addBook) } } })
.controller('firstController', ['$scope', function ($scope) { // console.log($scope);
    //這裏寫的controller代碼和上邊的controller寫是同樣的效果
}]);

 28. require的用法

記住1.require後邊的須要有一個引號。2.後面也須要一個引號。3.addBook方法是寫在this上而不是寫在scope上額。

angular.module('myApp', [])

    .directive('bookList', function () {
        return {
            restrict: 'ECAM',
            controller: function ($scope) {
                $scope.books = [
                    {
                        name: 'php'
                    },
                    {
                        name: 'javascript'
                    },
                    {
                        name: 'java'
                    }
                ];

                this.addBook = function(){

                    $scope.$apply(function(){
                        $scope.books.push({
                            name:'Angularjs'
                        })
                    });
                }
            },
            controllerAs:'bookListController',
            template: '<div><ul><li ng-repeat="book in books">{{book.name}}</li></ul><book-add></book-add></div>',
            replace:true

        }

    })

    .directive('bookAdd',function(){
        return {
            restrict:'ECAM',
            require:'^bookList',
            template:'<button type="button">添加</button>',
            replace:true,
            link:function(scope,iElement,iAttrs,bookListController){
                iElement.on('click',bookListController.addBook);
            }
        }
    })

    .controller('firstController', ['$scope', function ($scope) {
        // console.log($scope);


    }]);

這裏咱們能夠看到require能夠繼承父類的controller方法,和屬性。注意^bookList繼承父類的。

http://raowensheng.com/2014/05/09/angularjs%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8C%87%E4%BB%A4%E7%9A%84require%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E/

require的做用是爲了讓父子指令或者兄弟指令的controller之間搭建一個橋樑
也就是說父指令裏的controller裏面的數據能分享給子指令的controller
其中子指令的link第四個參數的值是父指令的controller對象的做用域上下文
require有兩個修飾符號:」?」、」^」
? : 若是require沒有找到相應的指令避免報錯,還能確保程序的正常執行
^ : 表示往父級查找

?^能夠一塊兒使用

 

29.scope  中@只能是值的綁定(簡單數據類型的綁定)而&卻能夠是對象的綁定。注意對象html頁面中的內容。若是是一個對象的話,咱們須要先把父類的controller中的東西放到一個屬性中,而後咱們的子controller而後從html標籤中的屬性中取值,而後付給本身的屬性。

scope(是針對子controller與父controller,可是咱們須要注意的時候與reqiuire的區別是,require爲了link中的第四個參數提供服務,而咱們的scope則須要把屬性綁定到html的屬性上邊)

這裏咱們能夠看出來,若是books是object類型,而title是簡單數據類型。

 


scope:爲當前指令建立一個新的做用域,而不是使之繼承父做用域 默認值記不清了 false繼承父元素的做用域,和父共享一個做用域 true建立一個新的做用域,可是仍是會繼承父做用域的屬性, object也是建立一個獨立的scope可是也能夠經過一些方式繼承父類
object:參數 & 做用域把父做用域的屬性包裝成一個函數,從而以函數的方法會讀寫父做用域的屬性。 注意這裏的單項綁定是方法,下邊的雙向綁定確實一個屬性。 =:做用域的屬性與父做用域的屬性進行雙向綁定,任何一方的修改均影響到對方。 @: 只能讀取父做用域裏的值單向綁定。



<div ng-app="myApp">

    <div ng-controller="firstController">
        {{
            books
        }}
        <div book-list books="books" parent-books="books" parent-title="{{title}}"> <!--注意這裏的title有{{}},簡單數據類型綁定屬性的時候有,而負責的數據類型則沒有-->

        </div>

    </div>



</div>
angular.module('myApp', [])

    .directive('bookList', function () {
        return {
            restrict: 'ECAM',
            controller: function ($scope) {

                // &books
                // $scope.books = $scope.a();

                // =books;
                // $scope.books = $scope.b;
                // $scope.b.push({name:'nodejs'});

                console.log($scope.c);

            },
            // 建立一個有繼承鏈的獨立做用域
            // scope:true,

            // 當爲對象的時候也會建立一個獨立的做用域
            scope:{
                // 將父元素books封裝成一個a函數
                // a:'&books'
                // 雙向綁定 b = parentBooks屬性對應的父做用域的表達式
                // b:'=parentBooks'

                // 使用簡單數據類型的方法
                c:'@parentTitle'
            },
            controllerAs:'bookListController',
            template: '<div><ul><li ng-repeat="book in books">{{book.name}}</li></ul></div>',
            replace:true

        }

    })


    .controller('firstController', ['$scope', function ($scope) {
        console.log($scope);

        $scope.books = [
            {
                name: 'php'
            },
            {
                name: 'javascript'
            },
            {
                name: 'java'
            }
        ];

        $scope.title = '張三';

    }]);

 30.自定義   

嵌套的directive

  heading:@heading 能夠簡寫成heading:@

<div ng-app="myApp">

    <div class="container">
        <div ng-controller="firstController">

            <kittencup-group>

                <kittencup-collapse ng-repeat="collapse in data" heading="{{collapse.title}}">
                    {{collapse.content}}
                </kittencup-collapse>

            </kittencup-group>

        </div>
    </div>



</div>
angular.module('myApp', [])
    // 數據
    .factory('Data', function () {
        return [
            {
                title: 'no1',
                content: 'no1-content'
            },
            {
                title: 'no2',
                content: 'no2-content'
            },
            {
                title: 'no3',
                content: 'no3-content'
            }
        ];
    })
    // 控制器
    .controller('firstController', ['$scope','Data',function ($scope,Data) {
        $scope.data = Data;
    }])

    .directive('kittencupGroup',function(){
        return {
            restrict:'E',
            replace:true,
            template:'<div class="panel-group" ng-transclude></div>',
            transclude:true,
            controllerAs:'kittencupGroupContrller',
            controller:function(){
                this.groups = [];

                this.closeOtherCollapse = function(nowScope){
                    angular.forEach(this.groups,function(scope){
                        if(scope !== nowScope){
                            scope.isOpen = false;
                        }
                    })
                }
            }
        }
    })

    .directive('kittencupCollapse',function(){
        return {
            restrict:'E',
            replace:true,
            require:'^kittencupGroup',
            templateUrl:'app/tmp/kittencupCollapse.html',
            scope:{
                heading:'@'
            },
            link:function(scope,element,attrs,kittencupGroupContrller){
                scope.isOpen = false;

                scope.changeOpen = function(){
                    scope.isOpen = !scope.isOpen;

                    kittencupGroupContrller.closeOtherCollapse(scope);
                }


                kittencupGroupContrller.groups.push(scope);
            },
            transclude:true
        }
    })

 一段angular指令本身平時練習的代碼:

var ng = angular.module('box',[]);
ng.directive('aa',function(){
    return {
        restrictive:"ECAM",
        template:"<div><h2>this is our world {{data}}</h2><span  ng-transclude></span><bb data='data' title='{{title}}'></bb></div>",
        replace: true,
        transclude:true,
        controller:function($scope){
            $scope.data = {'key':"beautiful"}
            this.al = function(){
                alert(1234);
            }
            $scope.title = "title";
        },
        controllerAs:"aacontroller"
    }
})
ng.controller('first',function($scope){

});
ng.directive('bb',function(){
    return{
        restrictive:"ECAM",
        require:'^?aa',
        template:"<div>this is son directive {{data}}<input ng-model='data'/></div>",
        replace: true,
        controller:function($scope){
            $scope.data = $scope.a;
        },
        scope:{
            a:'@title'
        },
        link:function(scope,el,attr,aacontroller){
            //el.on('click',aacontroller.al);
        }
    }
});

 

 32.優先級,小於0的不執行

    <div ng-controller="firstController">
        <custom-tags>原始數據</custom-tags>

        <div custom-tags2 custom-tags3>

        </div>
    </div>
var myApp = angular.module('myApp', [])

    .directive('customTags', function () {
        return {
            restrict: 'ECAM',
            template:'<div>新數據 <span ng-transclude></span></div>',
            replace: true,
            transclude:true
        }
    })

    .directive('customTags2', function () {
        return {
            restrict: 'ECAM',
            template:'<div>2</div>',
            replace: true,
            priority:-1
        }
    })

    .directive('customTags3', function () {
        return {
            restrict: 'ECAM',
            template:'<div>3</div>',
            replace: true,
            priority: 0,
            // 小於0的directive 都不會執行
            terminal:true
        }
    })

    .controller('firstController', ['$scope', function ($scope) {
        $scope.name = '張三';
    }]);

 33. $scope至關於js對象繼承的做用域鏈

34.

$provide方法都有快捷方法。
constant(name,object)
此方法首先運行,能夠用它來聲明整個應用範圍內的常量,而且讓它們在全部配置(config方法裏)和實例(controller,service等)方法中均可用。
run(initializationFn)
想要在注入啓動以後執行某些操做,而這些操做須要在頁面對用戶可用以前執行,可使用此方法。
好比 加載遠程的模板,須要在使用前放入緩存,或者在使用操做前判斷用戶是否登陸,未登陸能夠先去登陸頁面。

angular.module('myApp',[],['$provide',function($provide){
        console.log('config');
    // $provide.factory
    // $provide.service

    // $provide.constant
    // $provide.value;

}])

.config(function(APIKEY){
    console.log(APIKEY);
        console.log('config');
})

    // 在config以後controller等其餘服務以前。。
.run(function(){
    console.log('run');
})
    // 它只是能夠注入任何方法
.constant('APIKEY','xxxx')

    // 只能注入controller...service factory
.value('vension','1.0.0')

.controller('firstController',['APIKEY','vension',function(APIKEY,vension){
    console.log(APIKEY);
        console.log(vension);
        console.log('controller');


}]);

 35. ng-show ng-hide ng-if  能夠看:http://m.blog.csdn.net/article/details?id=44701769

angularJS中的ng-show、ng-hide、ng-if指令均可以用來控制dom元素的顯示或隱藏。ng-show和ng-hide根據所給表達式的值來顯示或隱藏HTML元素。當賦值給ng-show指令的值爲false時元素會被隱藏,值爲true時元素會顯示。ng-hide功能相似,使用方式相反。元素的顯示或隱藏是經過改變CSS的display屬性值來實現的。

ng-if指令能夠根據表達式的值在DOM中生成或移除一個元素。若是賦值給ng-if的表達式的值是false,那對應的元素將會從DOM中移除,不然生成一個新的元素插入DOM中。ng-if同no-show和ng-hide指令最本質的區別是,它不是經過CSS顯示或隱藏DOM節點,而是刪除或者新增結點。

36.服務返回一種方法的時候 http://www.runoob.com/try/try.php?filename=try_ng_services_filter2

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.static.runoob.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<body>

<div ng-app="myApp" ng-controller="myCtrl">
<p>在獲取數組 [255, 251, 200] 值時使用過濾器:</p>

<ul>
  <li ng-repeat="x in counts">{{x | myFormat}}</li>
</ul>

<p>過濾器使用服務將10進制轉換爲16進制。</p>
</div>

<script>
var app = angular.module('myApp', []);
app.service('hexafy', function() {
    this.myFunc = function (x) {
        return x.toString(16);
    }
});
app.filter('myFormat',['hexafy', function(hexafy) {
    return function(x) {
        return hexafy.myFunc(x);
    };
}]);
app.controller('myCtrl', function($scope) {
    $scope.counts = [255, 251, 200];
});
</script>

</body>
</html>

 一下就是本身angular開發中,常遇到的一些問題

37.若是ul li中的li點擊事件,原本想在Link中直接寫一個類型ul.find('li').on的發現不行的,只能在頁面的li中寫一個方法,而且傳入$event.利用

// 經過element轉換成 jquery對象
angular.element(event.target).html('切換狀態爲:' + $scope.status);

38.$scope與this的區別。

(1)$scope會繼承,可是this不會。

(2)在兩個directive中,若是一個directive經過require引用另一個directive中的東西,那麼方法必須寫在this中,若是寫在$scope中則不行。

39.const run value這個方法的區別和聯繫。

config先執行,而run在config以後在controller等其餘服務以前。。

const value

可是const只能注入方法中,

value// 只能注入controller...service factory

40.transclude:true實現的在於必須外邊的controller是有定義的,若是外邊的controller沒有定義沒效果.

41.AngularJS的學習 $on、$emit和$broadcast的使用

不過用的是$scope 發射和接受。

emit(name,data)向父control發射的。

而broadcast(name,data)是向子control發射的。 

相關文章
相關標籤/搜索