AngularJS入门教程(四)指令详解和实践

AngularJS除了强大的自定义服务外,还有更强大的指令。本章我们将继续前面的内容,更进一步的学习AngularJS的指令。

AngularJS的指令(Directive)简介

指令是AngularJS中另一个主要的特性,指令的作用可以用一句话描述,就是可以给HTML元素赋予特殊或自定义的行为,比如监听事件、视图模板代理等。在上文中我们使用过的ng-app、ng-controller、ng-model就是AngularJS中的指令。

AngularJS指令的命名

指令的命名和使用写法比较有意思,一般情况下在定义指令时推荐使用驼峰命名法,比如ngModel、ngApp,但是在HTML中大小写是不敏感的,所以在HTML中使用指令时推荐使用小写字母加破折号的形式,比如ng-model、ng-app。除了使用小写破折号这种方式,还有以下几种使用写法: 

  1. ng:model 
  2. ng_model 
  3. data-ng-bind 
  4. x-ng-bind

大家可以根据自己喜好选择使用写法,但是尽量保持写法统一。

AngularJS指令的形式

在AngularJS中,指令有四种表现形式,既标签形式、标签属性形式、标签class名称形式、注释形式:

<my-dir></my-dir>
<span my-dir="exp"></span>
<!-- directive: my-dir exp -->
<span class="my-dir: exp;"></span>

一般情况下,推荐使用标签形式和标签属性形式。

指令的使用

与Controller一样,指令也是通过AngularJS的Model创建的,使用directive(name, directiveFactory)方法创建指令,该方法有两个参数: 

  • 第一个参数为指令名称,命名规范在上文中已经说过了。 
  • 第二个参数是一个工厂函数,该函数需要返回一个对象,我们通过配置该对象中的不同属性从而告诉AngularJS内置的$compile服务实现指令的不同功能。

指令的类型

上文中说过指令的实现是通过工厂函数返回对象,然后通过配置对象的不同属性实现不同功能,所以设置指令的类型也是通过配置属性对象完成的:

var mainModule = angular.module("mainModule", []);
mainModule.directive("myDirective", function() {
  return {
    restrict: "A"
  };
});
mainModule.directive("myDirective1", function() {
  return {
    restrict: "E"
  };
});
mainModule.directive("myDirective2", function() {
  return {
    restrict: "AE"
  };
});
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Demo for Directive</title>
    <script src="../angular-1.5.8.js"></script>
    <script src="modules.js"></script>
  </head>
  <body ng-app="mainModule">
    <div my-directive></div>
    <my-directive1></my-directive1>
    <my-directive2></my-directive2>
    <!-- <div my-directive2></div> -->
  </body>
</html>

从上面的示例代码可以看出,可以通过配置返回对象的restrict属性设置指令的类型,可配置的值分别为: 

  • "A":代表且仅可代表标签属性类型的指令。 
  • "E":代表且仅可代表标签类型的指令。 
  • "C":代表且仅可代表class名称类型的指令。 
  • "M":代表且仅可代表注释类型的指令。

如果想设置一个多类型的指令,那么可以将类型标识写在一起,比如"AEC"代表既是标签属性类型,又是标签类型,还是class名称类型。如果不配置restrict属性,那么表示指令的类型为默认的"AE"类型。

通过指令封装UI模板

在前端应用的开发过程中,不同的页面常有很多一样的UI元素,如果每个页面都写一遍,那么在维护时就常会牵一发而动全身,AngularJS中的指令可以很好的解决这个问题,它可以将UI片段封装为一个指令,从而可以在不同的页面中复用,那么在维护时就是四两拨千斤的效果。下面来看看如何实现模板指令:

var mainModule = angular.module("mainModule", []);
mainModule.controller("MyController", function() {
  this.name = "Jason";
  this.job = "Developer";
});
mainModule.directive("myDirective", function() {
  return {
    template: "Name: {{mc.name}}, Job: {{mc.job}}"
  };
});
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Demo for Directive</title>
    <script src="../angular-1.5.8.js"></script>
    <script src="modules.js"></script>
  </head>
  <body ng-app="mainModule">
    <div ng-controller="MyController as mc">
      <my-directive></my-directive>
      <!-- <div my-directive></div> -->
    </div>
  </body>
</html>

上面的代码示例中,我们将本该写在HTML中的展示代码设置给了返回对象的template属性。为了能更好的管理UI模板,我们还可以将UI展示代码提炼成单独的HTML模板文件,并可以使用指令的templateUrl属性设置HTML模板文件名称,这样便可以大大降低指令和UI模板的耦合度:

mainModule.directive("myDirective", function() {
  return {
    templateUrl: "myTemplate.html"
  };
});
<!-- myTemplate.html -->
Name: {{mc.name}}, Job: {{mc.job}}

那么问题来了,如果UI模板文件很多的话,按上面的方法就要写很多个对应的指令,而且只是UI模板文件名称不一样而已,实在有点冗余。AngularJS提供了另外一种解决方法,那就是可以通过给模板指令设置相关属性,从而动态的加载UI模板文件,我们来看看如何实现:

// modules.js
var mainModule = angular.module("mainModule", []);
mainModule.controller("MyController", function() {
  this.name = "Jason";
  this.job = "Developer";
});
mainModule.directive("myDirective", function() {
  return {
    templateUrl: function(elem, attr) {
      return "myTemplate-" + attr.type + ".html";
    }
  };
});
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Demo for Directive</title>
    <script src="../angular-1.5.8.js"></script>
    <script src="modules.js"></script>
  </head>
  <body ng-app="mainModule">
    <div ng-controller="MyController as mc">
      <my-directive type="name"></my-directive>
      <my-directive type="job"></my-directive>
      <!-- <div my-directive type="name"></div> -->
      <!-- <div my-directive type="job"></div> -->
    </div>
  </body>
</html>
<!-- myTemplate-name.html -->
Name: {{mc.name}}
<!-- myTemplate-job.html -->
Job: {{mc.job}}

从上面的示例代码可以看出,template和templateUrl两个属性的值不只是接受字符串,还接受函数。要注意的是该函数默认带两个参数: 

  • 第一个参数代表当前的HTML DOM元素。 
  • 第二个参数代表当前HTML DOM元素的属性对象,在函数体内可以为该对象设置任何属性。

在上面的示例中,我们给代表当前DOM元素的属性对象设置了type属性,用于标识UI模板文件名称,这样我们就可以通过一个专有的模板指令来控制所有的UI模板文件了。

版权声明:本文为博主原创文章,未经博主允许不得转载。

AngularJS入门教程(四)指令详解和实践

: » AngularJS入门教程(四)指令详解和实践

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/251165.html

(0)
上一篇 2022年5月2日
下一篇 2022年5月2日

相关推荐

发表回复

登录后才能评论