zoukankan      html  css  js  c++  java
  • angular学习笔记(三十)-指令(10)-require和controller

    本篇介绍指令的最后两个属性,require和controller

    当一个指令需要和父元素指令进行通信的时候,它们就会用到这两个属性,什么意思还是要看栗子:

    html:

    <outer‐directive> 
        <inner‐directive></inner‐directive>
    </outer‐directive> 

    这里有两个指令,一个outer-directive指令元素,它里面又有一个inner-directive指令元素.

    js:

    app.directive('outerDirective',function(){
        return {
            scope: {},
            restrict: 'AE',
            controller: function($scope,$compile,$http){
                this.addChild = function(nestedDirective){ //this指代controller   
                console.log('Got the message from nested directive' + nestedDirective.message);
                }
            }
        }
    });    
    app.directive('innerDirective',function(){
        return {
            scope: {},
            restrict: 'AE',
            require: '^?outerDirective',
            link: function(scope,elem,attrs,ctrl){
                //第四个参数是你require的controller实例
                scope.message = 'Hi, Parent directive';
                ctrl.addChild(scope);
            }
        };
    });  

    在父元素指令里定义controller方法:

    function($scope,$compile,$http){   
       this.addChild = function(nestedDirective){ //this指代controller   
           console.log('Got the message from nested directive' + nestedDirective.message);
       }
    }

    controller方法是一个构造函数,可以给它添加对象的方法(什么是对象的方法看这里:mvc-javascript-web-application / 01.MVC和类 / 1.创建类库 / ex1.3(对象的方法).html).

    在子元素指令里定义require属性:require: '^?outerDirective',表示向外层寻找outerDirective指令,直到找到为止.注意:向外层寻找,也包括了自己本身,也就是说,自己可以寻找到自己身上的其它指令.

    '?'的作用是如果找不到也不会报错.

    定义了require属性后,link函数的第四个参数ctrl就是require到的指令的controller方法的实例.所以ctrl就有了addChild方法了. 

    下面看一个难一点的栗子:

    angular学习笔记(三十)-指令(9)-一个简单的指令示例这个栗子是单个子菜单的展开收起,下面使用require和controller,来扩展这个应用,改成多个菜单,要求点击某个菜单的时候展开此菜单,而其余菜单都收起:

    如下过程:

    html:

    <!DOCTYPE html>
    <html ng-app="accordionModule">
    <head>
      <title>20.10 指令-accordion</title>
      <meta charset="utf-8">
      <link href="../bootstrap.css" rel="stylesheet">
      <script src="../angular.min.js"></script>
      <script type="text/ng-template" id="vertical.html">
        <div class="btn-group-vertical" ng-transclude>
        </div>
      </script>
      <script type="text/ng-template" id="text.html">
        <div class="btn-group">
          <button class="btn btn-default dropdown-toggle" type="button" ng-click="toggle()">{{title}}<span class="caret"></span></button>
          <ul class="dropdown-menu" ng-show="ifShow" ng-transclude></ul>
        </div>
      </script>
      <script src="script.js"></script>
      <style type="text/css">
        body{
          padding:40px
        }
      </style>
    </head>
    <body>
      <div ng-controller="accordionCtrl">
        <accordion>
          <expander ng-repeat="list in lists" my-title="{{list.title}}">
            <li ng-repeat="content in list.contents">
              <a href="">{{content}}</a>
            </li>
          </expander>
        </accordion>
      </div>
    </body>
    </html>

    js:

    /*20.10 指令*/
    var accordionModule = angular.module('accordionModule',[]);
    accordionModule.controller('accordionCtrl',function($scope){
        $scope.lists = [
            {title:'标题1',contents:['bunny1','cat1','dog1']},
            {title:'标题2',contents:['bunny2','cat2','dog2']},
            {title:'标题3',contents:['bunny3','cat3','dog3']},
            {title:'标题4',contents:['bunny4','cat4','dog4']},
            {title:'标题5',contents:['bunny5','cat5','dog5']},
            {title:'标题6',contents:['bunny6','cat6','dog6']},
            {title:'标题7',contents:['bunny7','cat7','dog7']},
            {title:'标题8',contents:['bunny8','cat8','dog8']}
        ]
    });
    accordionModule.directive('accordion',function(){
        return {
            restrict:'EA',
            replace:true,
            templateUrl:'vertical.html',
            transclude:true,
            controller:function(){
                this.expanders = [];
                this.closeAll = function(scope){
                    angular.forEach(this.expanders,function(expander){
                        if(scope!=expander)
                        expander.ifShow = false;
                    })
                };
                this.addExpander = function(scope){
                    this.expanders.push(scope)
                }
            }
        }
    });
    accordionModule.directive('expander',function(){
        return {
            restrict:'EA',
            replace:true,
            templateUrl:'text.html',
            transclude:true,
            scope:{title:'@myTitle'},
            require:'^?accordion',
            link:function(scope,ele,attrs,ctrl){
                scope.ifShow = false;
                ctrl.addExpander(scope);
                scope.toggle = function(){
                    ctrl.closeAll(scope);
                    scope.ifShow = !scope.ifShow;
                }
            }
        }
    });

    下面来解释这个应用:

    1. accordion指令的controller的实例也就是link函数的第四个参数ctrl

    2. 将expander指令进行ng-repeat,渲染出多个子菜单.

    3. 由于这些子菜单是互相有关联而非独立存在的,所以将他们放在一个accordion指令中.

    4. 绑定数据模型都和单独的expander一样,唯一不同的是: 

        1) link函数中调用ctrl的addExpander方法,将每个expander的独立scope压入ctrl的expanders数组中.

        2) toggle()方法,它调用了accordion指令的controller的实例的方法.收起除了当前点击项以外其余的菜单.

    5. 注意ctrl是唯一的ctrl,而不是每次都实例化出一个新的实例.虽然有多个expander,但是它的ctrl指向的是同一个实例,所以expanders数组是唯一的.

    6. 这里expanders数组里存放是每个expander的scope,为什么是scope而不是element呢? 因为closeAll方法需要修改指令独立作用域下的ifShow的,所以这里数组里存放scope比较好写.

    完整代码: https://github.com/OOP-Code-Bunny/angular/blob/master/OREILLY/20.10%20%E6%8C%87%E4%BB%A4.html

                 https://github.com/OOP-Code-Bunny/angular/blob/master/OREILLY/script.js

                 

  • 相关阅读:
    JDBC
    JDBC连接MYSQL
    Servlet学习(1)
    Apache http server和tomcat的区别
    log4j(转)
    《打造Facebook》
    深入浅出Java三大框架SSH与MVC的设计模式
    Python 爬虫监控女神的QQ空间新的说说,实现秒赞,并发送说说内容到你的邮箱
    Python 爬虫监控女神的QQ空间新的说说,实现邮箱发送
    linux 进程消耗查看
  • 原文地址:https://www.cnblogs.com/liulangmao/p/3994215.html
Copyright © 2011-2022 走看看