zoukankan      html  css  js  c++  java
  • angular(常识)

    我觉得angularjs是前端框架,而jquery只是前端工具,这两个还是没有可比性的。

    看知乎上关于jquery和angular的对比http://www.zhihu.com/question/27471743

    优点: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,的确使我们的开发效率大大提高。

    2009年google feedback project 1500行
    为了解决ajax开发的痛苦

    1. 几个常用的概念
    a.客户端模板:模板和数据都会发送到浏览器中
    b.mvc:
    c.数据绑定:自动将Model和view间的数据同步。
    angular 实现数据绑定的方式,可以让我们把model当做程序中唯一可信的数据来源。view始终是model的投影。。当model发生变化时,会自动反映到view上。
    大多数的数据绑定都是单向的,当我们的model和view修改后要去提醒另外一个的话,就必须使用ajax之类的,比如jquery还要手动的同步,这样子的话,增加了不必要的麻烦。
    d.依赖注入:

    2.依赖注入 的详解

    回顾下spring中的ioc 控制反转:

    控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心。 控制反转一般分为两种类型,依赖注入(Dependency Injection,简称DI)和依赖查找(Dependency Lookup)。依赖注入应用比较广泛。

    个人理解:就是本来需要你在程序设计时,创建的某些对象,交给spring来管理,当你需要某个时候需要某个对象的时候spring在给你,这样子对象的生命周期之类的就由spring来维护了。

    js的依赖注入:(我们这里所说的依赖注入和上面的ioc或者di还是有点不同的,我们这里更局限在依赖这个词)
    方法1:

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

    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发射的。 

  • 相关阅读:
    2019 SDN上机第7次作业
    2019 SDN上机第六次作业
    2019 SDN上机第5次作业
    SDN课程阅读作业(2)
    2019 SDN上机第4次作业
    2019 SDN阅读作业
    2019 SDN上机第3次作业
    第09组 团队Git现场编程实战
    预习非数值数据的编码方式
    预习原码补码
  • 原文地址:https://www.cnblogs.com/coding4/p/5549812.html
Copyright © 2011-2022 走看看