angularjs 指令详解 - template, restrict, replace

经过指令机制,angularjs 提供了一个强大的扩展系统,咱们能够经过自定义指令来扩展本身的指令系统。html

怎样定义本身的指令呢?git

咱们经过 Bootstrap UI 来学习吧。这个项目使用 angularjs 将 Bootstrap 3 进行了封装,是咱们学习 angularjs 很好的样例。angularjs

从 Alert 开始

首先,咱们从比较简单的 alert 指令来开始学习。github

在 Bootstrap 中,警告框使用类 alert 来表示, 经过 alert-success, alert-info, alert-warning, alert-danger 来表示不一样类型的警告。bootstrap

<div class="alert alert-success">...</div>
<div class="alert alert-info">...</div>
<div class="alert alert-warning">...</div>
<div class="alert alert-danger">...</div>

对于可关闭的警告框来讲,还能够用一个可选的.alert-dismissable和关闭按钮,可是,这是经过脚原本实现的,在 bootstrap ui 这里没有使用。浏览器

<div class="alert alert-warning alert-dismissable">
  <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
  <strong>Warning!</strong> Best check yo self, you're not looking too good.
</div>

bootstrap UI 中的用法

在 Bootstrap UI 的示例中,咱们能够直接经过自定义的 alert 来定义一个提示。其中的 type 用来定义提示的类型,提示的信息内容经过绑定来处理。app

<div ng-controller="AlertDemoCtrl">
  <alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">{{alert.msg}}</alert>
  <button class='btn btn-default' ng-click="addAlert()">Add Alert</button>
</div>

对应的脚本函数

function AlertDemoCtrl($scope) {
  $scope.alerts = [
    { type: 'danger', msg: 'Oh snap! Change a few things up and try submitting again.' },
    { type: 'success', msg: 'Well done! You successfully read this important alert message.' }
  ];

  $scope.addAlert = function() {
    $scope.alerts.push({msg: "Another alert!"});
  };

  $scope.closeAlert = function(index) {
    $scope.alerts.splice(index, 1);
  };

}

bootstrap UI 中的定义

下面就是指令的定义了。学习

 

angular.module('ui.bootstrap.alert', [])

.controller('AlertController', ['$scope', '$attrs', function ($scope, $attrs) {
  $scope.closeable = 'close' in $attrs;
}])

.directive('alert', function () {
  return {
    restrict:'EA',
    controller:'AlertController',
    templateUrl:'template/alert/alert.html',
    transclude:true,
    replace:true,
    scope: {
      type: '@',
      close: '&'
    }
  };
});

最终生成的标记为:ui

<div ng-controller="AlertDemoCtrl" class="ng-scope">
    <!-- ngRepeat: alert in alerts -->
    <div class="alert ng-isolate-scope alert-danger" ng-class="&quot;alert-&quot; + (type || &quot;warning&quot;)" ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">
        <button ng-show="closeable" type="button" class="close" ng-click="close()">×</button>
        <div ng-transclude=""><span class="ng-scope ng-binding">Oh snap! Change a few things up and try submitting again.</span></div>
    </div>

    <!-- end ngRepeat: alert in alerts -->
    <div class="alert ng-isolate-scope alert-success" ng-class="&quot;alert-&quot; + (type || &quot;warning&quot;)" ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">
        <button ng-show="closeable" type="button" class="close" ng-click="close()">×</button>
        <div ng-transclude=""><span class="ng-scope ng-binding">Well done! You successfully read this important alert message.</span></div>
    </div><!-- end ngRepeat: alert in alerts -->
    <button class="btn btn-default" ng-click="addAlert()">Add Alert</button>
</div>
看不懂!没有关系,咱们慢慢来。

从模版开始

好比说,在下面的代码中,你但愿经过 my-customer 将一个内容为空白的 div 变成内容为绑定名字和地址的文本内容

<div ng-controller="Ctrl">
  <div my-customer></div>
</div>

好比生成下面的结果:

<div ng-controller="Ctrl">
  <div>Name: {{customer.name}} Address: {{customer.address}}</div>
</div>

内嵌模版

对于以上的要求,咱们能够定义一个名为 my-customer 的指令。而后,说明这个指令将会生成元素中间的内容,咱们称之为模版的内容。

angular.module('docsSimpleDirective', [])
  .controller('Ctrl', function($scope) {
    $scope.customer = {
      name: 'Naomi',
      address: '1600 Amphitheatre'
    };
  })
  .directive('myCustomer', function() {
    return {
      template: 'Name: {{customer.name}} Address: {{customer.address}}'
    };
  });

directive 表示咱们要定义一个自定义的指令,指令的名称为 myCustomer,后面的函数用来定义指令的特征

template 表示咱们的指令使用的模版,你会看到,它的值就是咱们准备生成的内容。

不过,你会说,且慢,我但愿使用 myCustomer 元素,而不是 Attribute ,那又该怎么办呢?

默认状况下,指令只能做为元素的 attribute 使用,若是但愿用在其它的地方,那么你须要学习第二个属性 restrict

指令的使用范围

restrict 的取值能够有三种:

  • A 用于元素的 Attribute,这是默认值
  • E 用于元素的名称
  • C 用于 CSS 中的 class

好比说,咱们这样定义指令。

var app = angular.module("app", [])
    .directive("hello", function () {
        var option = {
            restrict: "AEC",
            template: "Hello, Directive",
        };
        return option;
    })

因为咱们指定了能够用于三种状况下,那么,就能够以下三种形式来使用这个指令

<!-- 元素 -->
<div>
    <hello></hello>
</div>

<!-- 属性-->
<div>
    <div hello></div>
</div>

<!-- class -->
<div>
    <div class="hello"></div>
</div>

输出的结果分别以下:

<!-- 元素 -->
<div>
    <hello>Hello, Directive</hello>
</div>
<!-- 属性-->
<div>
    <div hello="">Hello, Directive</div>
</div>
<!-- class -->
<div>
    <div class="hello">Hello, Directive</div>
</div>

替换元素

下一个你须要知道的参数为 replace,顾名思义,这是替换的意思,默认为 false,就是将模版的内容追加到元素中,若是设置为 true,那么模版的内容将会替换元素的内容。

原来的输出将会成为下面的样子,实际上,你在页面中将会看不到输出的内容,hello 元素浏览器是不认识的,而其它两种方式,咱们又没有生成任何的元素。

<!-- 元素 -->
<div>
    <hello></hello>
</div>
<!-- 属性-->
<div>
    <div hello=""></div>
</div>
<!-- class -->
<div>
    <div class="hello"></div>
</div>

若是咱们将模版更新为一个元素,以下所示。

var app = angular.module("app", [])
    .directive("hello", function () {
        var option = {
            restrict: "AECM",
            template: "<h3>Hello, Directive</h3>",
            replace: true
        };
        return option;
    })

此次,你将会看到在 replace 为 true 状况下的元素了。

<!-- 元素 -->
<div>
    <h3>Hello, Directive</h3>
</div>
<!-- 属性-->
<div>
    <h3 hello="">Hello, Directive</h3>
</div>
<!-- class -->
<div>
    <h3 class="hello">Hello, Directive</h3>
</div>

 

transclusion 嵌入

若是咱们在上面的元素中这么写会怎样呢?

<!-- 元素 -->
<div>
    <hello>12345678</hello>
</div>

你会发现 12345678 消失了,这个元素彻底被模版替换了。若是咱们须要保留这些内容怎么处理呢?

transclusion 指的是定义模版的元素如何处理问题,好比,在使用指令的时候,指令中包含了内容,那么这些内容咱们是否直接被替换为模版,仍是将这些内容嵌入到模版中。

在使用它的时候,须要在两个地方说明,一是在指令中说明须要嵌入,二是在模版中说明嵌入到哪里。

var app = angular.module("app", [])
    .directive("hello", function () {
        var option = {
            restrict: "AECM",
            template: "<h3>Hello, Directive, <span ng-transclude></span></h3>",
            replace: true,
            transclude: true
        };
        return option;
    })

而后,在模版中说明嵌入的位置。

 template: "<h3>Hello, Directive, <span ng-transclude></span></h3>",

页面中的使用。

<hello>12345678</hello>

最后,生成的结果以下。

<h3>Hello, Directive, <span ng-transclude=""><span class="ng-scope">12345678</span></span></h3>

 

看看 alert 使用的模版

模版的实际定义以下。

<div class="alert" ng-class="{'alert-{{type || 'warning'}}': true, 'alert-dismissable': closeable}" role="alert">
    <button ng-show="closeable" type="button" class="close" ng-click="close()">
        <span aria-hidden="true">&times;</span>
        <span class="sr-only">Close</span>
    </button>
    <div ng-transclude></div>
</div>

 在生成以后,alert 被替换为了 div 元素,至于关闭按钮是否显示出来,取决于 closeable 属性的值。

 replace 定义为真,表示使用模版的定义替换原来的元素,而 transclude 用来把内容填充到目标位置。在内嵌的 div 元素中使用了 ng-transclude 指示了填充的目标位置。

相关文章
相关标签/搜索