• 让Directive支持传入数据
    • Directive的scope
    • scope中的配置
      • 在一个ng-ontroller中放入多个相同的Directive
    • 通过ng-repeat和directive一起显示数据
      • 在Directive中修改控制器中的数据
      • 以只读的方式传入数据
    • 在Directive中进行函数回调

    让Directive支持传入数据

    在第一节中,我们使用的Directive,可以直接获取并显示控制器中的数据(人的名称和性别)。但是,如果我们有多个人的信息需要显示怎么处理?这个问题其实非常常见,因为Directive通常是将需要在界面中重复使用的部分抽象出来,便于一次修改,多处地方生效(如博客的评论的列表显示)。

    如果我们按照现在的代码结构(详见第一节),期望放置不同的人的信息,只能采取重复多个控制器的方式,可能的代码如下:

    1. <!DOCTYPE html>
    2. <html lang="zh" ng-app="App">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>{{"学习AngularJS 1.x"}}</title>
    6. <link type="text/css" rel="stylesheet" href="css/style.css">
    7. </head>
    8. <body>
    9. <div ng-controller="FirstCtrl">
    10. <!-- 第一个人的信息 -->
    11. <people></people>
    12. </div>
    13. <div ng-controller="SecondCtrl">
    14. <!-- 第二个人的信息 -->
    15. <people></people>
    16. </div>
    17. <script type="text/javascript" src="components/angular/angular.js"></script>
    18. <script type="text/javascript" src="js/app.js"></script>
    19. </body>
    20. </html>

    这样做,无法实现动态化的列表,是无法实现我们期望的功能的。我们理想中的情况应该是什么样子呢?当然是能够并列放置这些Directive,通过传入不同的数据来让Directive展示不同的内容。

    1. <div ng-controller="FirstCtrl">
    2. <!-- 第一个人的信息 -->
    3. <div people='peopleOneInfo'></div>
    4. <!-- 第二个人的信息 -->
    5. <div people='peopleTwoInfo'></div>
    6. </div>

    这样的功能,可以通过配置Directive的scope定义实现。

    Directive的scope

    在之前学习控制器ng-controller的使用过程中,我们使用了$scope功能。$scope用于提供对接HTML和JavaScript对应模块的功能。

    而Directive在默认情况下,是没有自动绑定一个$scope的。也就是说,在默认情况下,Directive无法在JavaScript中接收传入的数据(因为缺少一个存储信息的载体),形成我们期望的效果。但是,Directive提供了非常简单的定义一个scope的功能:

    1. App.directive("people", function(){
    2. return {
    3. restrict: "A",
    4. scope:{
    5. info: "="
    6. },
    7. template : "<p>姓名:{{info.name}}</p><p>性别:{{info.sex}}</p>"
    8. }
    9. });
    10. App.controller("FirstCtrl", function ($scope) {
    11. $scope.harry = {
    12. name: "Harry",
    13. sex : "男"
    14. };
    15. });

    注意,这里我将restrict从”E”(element元素)改变成为了”A”(attribute 属性),这样它的使用方法有了一些变化:

    1. <div ng-controller="FirstCtrl">
    2. <div people info="harry"></div>
    3. </div>

    在HTML代码里,我们为div元素配置了一个people的属性和一个info属性;并将FirstCtrl的$scope.harry传入给了info。最终的显示效果如下:

    图5-5 传入数据的Directive

    scope中的配置

    可以看到,在上方的JavaSciprt文件中,我们对scope的定义使用了如下结构:

    1. scope:{
    2. info: "="
    3. }

    首先,scope:{}是告诉这个Directive它需要自己存储信息(类似于建立一个基于这个Directive的$scope)。

    info: "=" 这段配置,告诉Directive从HTML标签中,获取名为info的属性,并将它的值存储在scope.info中。这样,我们就达到了存储数据的效果。

    在一个ng-ontroller中放入多个相同的Directive

    下面,我们在FirstCtrl中增加几个人的数据,并将它们通过Directive显示出来:

    1. //在FirstCtrl中加入如下代码
    2. $scope.anotherPerson = {
    3. name : "张三",
    4. sex : "男"
    5. };
    1. <div ng-controller="FirstCtrl">
    2. <div people info="harry"></div>
    3. <div people info="anotherPerson"></div>
    4. </div>

    运行效果如下:

    图5-6 在一个控制器中多个Directive

    通过ng-repeat和directive一起显示数据

    知道了如何传入数据,那么我们就可以将Directive的使用和ng-repeat结合起来,实现列表显示数据的效果。

    我们先将FirstCtrl的数据变化为一个array

    1. App.controller("FirstCtrl", function ($scope) {
    2. $scope.people = [
    3. {
    4. name: "Harry",
    5. sex: "男"
    6. },
    7. {
    8. name: "张三",
    9. sex: "男"
    10. }
    11. ];
    12. });
    1. <div ng-controller="FirstCtrl">
    2. <span ng-repeat="person in peopleList">
    3. <div people info="person"></div>
    4. </span>
    5. </div>

    实现的效果与上一张图片一样。(具体的页面HTML代码会有差异,请您自行测试查看)

    在Directive中修改控制器中的数据

    以上我们看到的示例只是将数据显示了出来,如果我们期望在Directive中修改这些数据如何处理呢?

    其实很简单,将template中原先显示的数据的部分,替换为input即可。

    1. App.directive("people", function () {
    2. return {
    3. restrict: "A",
    4. scope: {
    5. info: "="
    6. },
    7. template: "<input type='text' ng-model='info.name'><p>性别:{{info.sex}}</p>"
    8. }
    9. });
    1. <div ng-controller="FirstCtrl">
    2. {{ peopleList | json}}
    3. <span ng-repeat="person in peopleList">
    4. <div people info="person"></div>
    5. </span>
    6. </div>

    刷新界面后,我们可以在输入框中尝试修改。效果如下:

    图5-7 在Directive中修改数据

    以只读的方式传入数据

    除了以等号=直接传入对象之外,Directive也支持直接传入文本,使用@符号。

    1. App.directive("people", function () {
    2. return {
    3. restrict: "A",
    4. scope: {
    5. name: "@",
    6. sex : "@"
    7. },
    8. template: "<input type='text' ng-model='name'><p>性别:{{sex}}</p>"
    9. }
    10. });
    1. <div ng-controller="FirstCtrl">
    2. {{ peopleList | json}}
    3. <span ng-repeat="person in peopleList">
    4. <!-- 注意此处的数据传入方法 -->
    5. <div people name="{{person.name}}" sex="{{person.sex}}"></div>
    6. </span>
    7. </div>

    运行效果:

    图5-8 在Directive中传入字符串

    可以看到,我们在Directive中传入的数据进行的数据修改,并未反馈到FirstCtrl中。

    在Directive中进行函数回调

    上面我们介绍了等号=@符号的使用方法,它们分别对应传入对象和文本。但是,如果我们期望传入一个回调函数呢?这样我们就可以实现如封装一个按钮为一个Directive,然后让它在点击后实现我们期望的功能的效果。

    这就需要使用到&符号,下面我们来看看实际的例子(这个例子比较复杂,请仔细分析研读):

    1. var App = angular.module("App", []);
    2. App.directive("formDirective", function () {
    3. return {
    4. restrict: "A",
    5. scope: {
    6. //这里使用&符号来接受传入的函数
    7. btnClick: "&"
    8. //注意:这里没有加入下方的value模型
    9. },
    10. template:
    11. //一个用于输入文字的输入框,绑定到value上
    12. "<input type='text' ng-model='value'><br>" +
    13. //提交的按钮,绑定上方scope的btnClick方法
    14. //注意传入参数的方式和HTML中具体使用的方式
    15. "<input type='button' value='提交' ng-click='btnClick({message:value})'>"
    16. }
    17. });
    18. App.controller("FirstCtrl", function ($scope) {
    19. $scope.clickBtnCallback = function (msg) {
    20. alert("点击了按钮!信息是:" + msg);
    21. }
    22. });

    对应的HTML代码:

    1. <!DOCTYPE html>
    2. <html lang="zh" ng-app="App">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>{{"学习AngularJS 1.x"}}</title>
    6. <link type="text/css" rel="stylesheet" href="css/style.css">
    7. </head>
    8. <body>
    9. <div ng-controller="FirstCtrl">
    10. <!-- 注意这里绑定btn-click/btnClick中传入的参数的命名 -->
    11. <div form-directive btn-click="clickBtnCallback(message)"></div>
    12. </div>
    13. <script type="text/javascript" src="components/angular/angular.js"></script>
    14. <script type="text/javascript" src="js/app.js"></script>
    15. </body>
    16. </html>

    运行结果:

    图5-8 在Directive中传入函数和数据回传