- 让Directive支持传入数据
- Directive的
scope scope中的配置- 在一个
ng-ontroller中放入多个相同的Directive
- 在一个
- 通过
ng-repeat和directive一起显示数据- 在Directive中修改控制器中的数据
- 以只读的方式传入数据
- 在Directive中进行函数回调
- Directive的
让Directive支持传入数据
在第一节中,我们使用的Directive,可以直接获取并显示控制器中的数据(人的名称和性别)。但是,如果我们有多个人的信息需要显示怎么处理?这个问题其实非常常见,因为Directive通常是将需要在界面中重复使用的部分抽象出来,便于一次修改,多处地方生效(如博客的评论的列表显示)。
如果我们按照现在的代码结构(详见第一节),期望放置不同的人的信息,只能采取重复多个控制器的方式,可能的代码如下:
<!DOCTYPE html><html lang="zh" ng-app="App"><head><meta charset="UTF-8"><title>{{"学习AngularJS 1.x"}}</title><link type="text/css" rel="stylesheet" href="css/style.css"></head><body><div ng-controller="FirstCtrl"><!-- 第一个人的信息 --><people></people></div><div ng-controller="SecondCtrl"><!-- 第二个人的信息 --><people></people></div><script type="text/javascript" src="components/angular/angular.js"></script><script type="text/javascript" src="js/app.js"></script></body></html>
这样做,无法实现动态化的列表,是无法实现我们期望的功能的。我们理想中的情况应该是什么样子呢?当然是能够并列放置这些Directive,通过传入不同的数据来让Directive展示不同的内容。
<div ng-controller="FirstCtrl"><!-- 第一个人的信息 --><div people='peopleOneInfo'></div><!-- 第二个人的信息 --><div people='peopleTwoInfo'></div></div>
这样的功能,可以通过配置Directive的scope定义实现。
Directive的scope
在之前学习控制器ng-controller的使用过程中,我们使用了$scope功能。$scope用于提供对接HTML和JavaScript对应模块的功能。
而Directive在默认情况下,是没有自动绑定一个$scope的。也就是说,在默认情况下,Directive无法在JavaScript中接收传入的数据(因为缺少一个存储信息的载体),形成我们期望的效果。但是,Directive提供了非常简单的定义一个scope的功能:
App.directive("people", function(){return {restrict: "A",scope:{info: "="},template : "<p>姓名:{{info.name}}</p><p>性别:{{info.sex}}</p>"}});App.controller("FirstCtrl", function ($scope) {$scope.harry = {name: "Harry",sex : "男"};});
注意,这里我将restrict从”E”(element元素)改变成为了”A”(attribute 属性),这样它的使用方法有了一些变化:
<div ng-controller="FirstCtrl"><div people info="harry"></div></div>
在HTML代码里,我们为div元素配置了一个people的属性和一个info属性;并将FirstCtrl的$scope.harry传入给了info。最终的显示效果如下:

scope中的配置
可以看到,在上方的JavaSciprt文件中,我们对scope的定义使用了如下结构:
scope:{info: "="}
首先,scope:{}是告诉这个Directive它需要自己存储信息(类似于建立一个基于这个Directive的$scope)。
info: "=" 这段配置,告诉Directive从HTML标签中,获取名为info的属性,并将它的值存储在scope.info中。这样,我们就达到了存储数据的效果。
在一个ng-ontroller中放入多个相同的Directive
下面,我们在FirstCtrl中增加几个人的数据,并将它们通过Directive显示出来:
//在FirstCtrl中加入如下代码$scope.anotherPerson = {name : "张三",sex : "男"};
<div ng-controller="FirstCtrl"><div people info="harry"></div><div people info="anotherPerson"></div></div>
运行效果如下:

通过ng-repeat和directive一起显示数据
知道了如何传入数据,那么我们就可以将Directive的使用和ng-repeat结合起来,实现列表显示数据的效果。
我们先将FirstCtrl的数据变化为一个array:
App.controller("FirstCtrl", function ($scope) {$scope.people = [{name: "Harry",sex: "男"},{name: "张三",sex: "男"}];});
<div ng-controller="FirstCtrl"><span ng-repeat="person in peopleList"><div people info="person"></div></span></div>
实现的效果与上一张图片一样。(具体的页面HTML代码会有差异,请您自行测试查看)
在Directive中修改控制器中的数据
以上我们看到的示例只是将数据显示了出来,如果我们期望在Directive中修改这些数据如何处理呢?
其实很简单,将template中原先显示的数据的部分,替换为input即可。
App.directive("people", function () {return {restrict: "A",scope: {info: "="},template: "<input type='text' ng-model='info.name'><p>性别:{{info.sex}}</p>"}});
<div ng-controller="FirstCtrl">{{ peopleList | json}}<span ng-repeat="person in peopleList"><div people info="person"></div></span></div>
刷新界面后,我们可以在输入框中尝试修改。效果如下:

以只读的方式传入数据
除了以等号=直接传入对象之外,Directive也支持直接传入文本,使用@符号。
App.directive("people", function () {return {restrict: "A",scope: {name: "@",sex : "@"},template: "<input type='text' ng-model='name'><p>性别:{{sex}}</p>"}});
<div ng-controller="FirstCtrl">{{ peopleList | json}}<span ng-repeat="person in peopleList"><!-- 注意此处的数据传入方法 --><div people name="{{person.name}}" sex="{{person.sex}}"></div></span></div>
运行效果:

可以看到,我们在Directive中传入的数据进行的数据修改,并未反馈到FirstCtrl中。
在Directive中进行函数回调
上面我们介绍了等号=和@符号的使用方法,它们分别对应传入对象和文本。但是,如果我们期望传入一个回调函数呢?这样我们就可以实现如封装一个按钮为一个Directive,然后让它在点击后实现我们期望的功能的效果。
这就需要使用到&符号,下面我们来看看实际的例子(这个例子比较复杂,请仔细分析研读):
var App = angular.module("App", []);App.directive("formDirective", function () {return {restrict: "A",scope: {//这里使用&符号来接受传入的函数btnClick: "&"//注意:这里没有加入下方的value模型},template://一个用于输入文字的输入框,绑定到value上"<input type='text' ng-model='value'><br>" +//提交的按钮,绑定上方scope的btnClick方法//注意传入参数的方式和HTML中具体使用的方式"<input type='button' value='提交' ng-click='btnClick({message:value})'>"}});App.controller("FirstCtrl", function ($scope) {$scope.clickBtnCallback = function (msg) {alert("点击了按钮!信息是:" + msg);}});
对应的HTML代码:
<!DOCTYPE html><html lang="zh" ng-app="App"><head><meta charset="UTF-8"><title>{{"学习AngularJS 1.x"}}</title><link type="text/css" rel="stylesheet" href="css/style.css"></head><body><div ng-controller="FirstCtrl"><!-- 注意这里绑定btn-click/btnClick中传入的参数的命名 --><div form-directive btn-click="clickBtnCallback(message)"></div></div><script type="text/javascript" src="components/angular/angular.js"></script><script type="text/javascript" src="js/app.js"></script></body></html>
运行结果:

