本篇介绍指令的最后两个属性,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

angular学习笔记(三十)-指令(10)-require和controller的更多相关文章

  1. angular学习笔记(三十)-指令(5)-link

    这篇主要介绍angular指令中的link属性: link:function(scope,iEle,iAttrs,ctrl,linker){ .... } link属性值为一个函数,这个函数有五个参数 ...

  2. angular学习笔记(三十)-指令(7)-compile和link(2)

    继续上一篇:angular学习笔记(三十)-指令(7)-compile和link(1) 上一篇讲了compile函数的基本概念,接下来详细讲解compile和link的执行顺序. 看一段三个指令嵌套的 ...

  3. angular学习笔记(三十)-指令(7)-compile和link(1)

    这篇主要讲解指令中的compile,以及它和link的微妙的关系. link函数在之前已经讲过了,而compile函数,它和link函数是不能共存的,如果定义了compile属性又定义link属性,那 ...

  4. angular学习笔记(三十)-指令(6)-transclude()方法(又称linker()方法)-模拟ng-repeat指令

    在angular学习笔记(三十)-指令(4)-transclude文章的末尾提到了,如果在指令中需要反复使用被嵌套的那一坨,需要使用transclude()方法. 在angular学习笔记(三十)-指 ...

  5. angular学习笔记(三十)-指令(2)-restrice,replace,template

    本篇主要讲解指令中的 restrict属性, replace属性, template属性 这三个属性 一. restrict: 字符串.定义指令在视图中的使用方式,一共有四种使用方式: 1. 元素: ...

  6. angular学习笔记(三十)-指令(1)-概述

    之前在 angular学习笔记(十九)-指令修改dom 里面已经简单的提到了angular中的指令,现在来详细的介绍 '指令' 一.指令的创建: dirAppModule.directive('dir ...

  7. angular学习笔记(三十)-指令(8)-scope

    本篇讲解指令的scope属性: scope属性值可以有三种: 一.scope:false 默认值,这种情况下,指令的作用域就是指令元素当前所在的作用域. 二.scope:true 创建一个继承了父作用 ...

  8. angular学习笔记(三十)-指令(7)-compile和link(3)

    本篇接着上一篇来讲解当指令中带有template(templateUrl)时,compile和link的执行顺序: 把上一个例子的代码再进行一些修改: 1.将level-two指令改成具有templa ...

  9. angular学习笔记(三十)-指令(4)-transclude

    本篇主要介绍指令的transclude属性: transclude的值有三个: 1.transclude:false(默认值) 不启用transclude功能. 2.transclude:true 启 ...

随机推荐

  1. 使用 ODP.NET 访问 Oracle(.net如何访问Oracle)详解

    1,什么是ODF .NE,?就是Oracle 为 .NET (ODP.NET) 专门编写了 Oracle Data Provider,一个用于 Microsoft .NET 环境下的 Oracle 数 ...

  2. 比较MessageListActivity使用不同的layout

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  3. 【TP3.2.X】linux环境下TP3.2.X的各个目录权限

    1.将整个项目文件 所属设置成www:www,单个文件夹 755 2.Application 单文件夹是755 3.Runtime.Public .Uploads  均是  -R 777

  4. CentOS vps下,安装xfce/KDE/GNOME桌面+vncserver进行远程管理

    CentOS vps下,安装xfce/KDE/GNOME桌面+vncserver进行远程管理 首先安装桌面环境,我选择的是xfce,轻量级桌面,小巧实用不占太多内存,(占用内存方面,xfce少于kde ...

  5. Ubuntu 10.04里安装强大抓图工具Shutter

    Shutter 原名叫GScrot,是一款Linux下很强大的抓图工具,支持截取全屏幕,窗口,自选区域以及网页的图像,并且截取后的图像还可以简单编辑,Shutter还支持插件功能,矩齿,边缘化,碎纸, ...

  6. 使用安全rm

    rm命令像一把刀子一样,玩不好会伤到自己.不要觉得自己头脑清醒,人总有犯迷糊的时候. 在.bashrc中设置PATH=/home/me/bin/:$PATH 在自己的bin目录下,添加rm脚本mv - ...

  7. php安装 出现Sorry, I cannot run apxs. ***错误解决方法

    # tar zvxf php-5.1.2.tar.gz# cd php-5.1.2# ./configure --prefix=/usr/local/php --with-mysql=/usr/loc ...

  8. 做一个合格的Team Leader -- 领导和管理基本概念 三种激励手段:恐吓、贪念、承诺

    做一个合格的Team Leader -- 基本概念 1.领导和管理   人们乐于被领导:他们不喜欢被管理,不喜欢像牛一样被驱赶或指挥.   管理者强迫人们服从他们的命令,而领导者则会带领他们一起工作. ...

  9. java结合使用Jsonp的例子

    更多:js跨域问题解释 解决方案值使用jsonp或jQuery Jsonp和java操作例子 介绍JSONP之前,先简单的介绍一些JSON.JSON是JavaScript Object Notatio ...

  10. c运行库、c标准库、windows API的区别和联系

    C运行时库函数C运行时库函数是指C语言本身支持的一些基本函数,通常是汇编直接实现的.  API函数API函数是操作系统为方便用户设计应用程序而提供的实现特定功能的函数,API函数也是C语言的函数实现的 ...