javascript代码实例教程-AngularJS自定义Directive

发布时间:2019-01-18 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了javascript代码实例教程-AngularJS自定义Directive脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
小宝典致力于为广大程序猿(媛)提供高品质的代码服务,请大家多多光顾小站,小宝典在此谢过。 (编辑完这篇之后,发现本篇内容应该属于AngularJS的进阶,内容有点多,有几个例子偷懒直接用了官方的Demo稍加了一些注释,敬请见谅)。

 

前面一篇介绍了各种常用的AngularJS内建的Directives以及对应的代码实例。这篇我们再看看如何创建自己的Directive吧!

 

什么时候需要自定义Directive?

1. 使你的HtML更具语义化,不需要深入研究代码和逻辑即可知道页面的大致逻辑。

 

2. 抽象一个自定义组件,在其他地方进行重用。

 

 

 

看一下如下2个代码片段

 

示例1:

 

 

 1 <body>

 2     <p>

 3         <p>This is your class name.</p>

 4         <p>

 5             <p>Your teacher:</p>

 6             <p>;mr. Wang</p>

 7             <p>35 years old</p>

 8             <p>English</p>

 9             <p>Descriptions: 1.85cm tall, wITh a pair of brown glasses, unmarried, easy going etc.</p>

10         </p>

11         <p>

12             <p>

13                 <p>Students in the class:</p>

14                 <p>

15                     <p>Jack</p>

16                     <p>Male</p>

17                     <p>15</p>

18                     <p>Description: Smart ...</p>

19                 </p>

20                 <p>

21                     <p>May</p>

22                     <p>Female</p>

23                     <p>14</p>

24                     <p>Description: Diligent ...</p>

25                 </p>

26                 <p>

27                     <p>Tom</p>

28                     <p>Male</p>

29                     <p>15</p>

30                     <p>Description: Naughty ...</p>

31                 </p>

32                 <p>

33                     <p>Alice</p>

34                     <p>Female</p>

35                     <p>14</p>

36                     <p>Description: Smart ...</p>

37                 </p>

38             </p>

39         </p>

40     </p>

41 </body>

 

示例2:

 

1 <body ng-app>

2     <class-info>

3         <teacher-info></teacher-info>

4         <student-infos></student-infos>

5     </class-info>

6 </body>

 

 

示例1中的代码你可能要完整的看完才能知道逻辑(当然示例1也不复杂,你可以想象下真实的场景要比这个复杂的多的多),不是说示例2中的代码少(逻辑被转移到其他地方去了),而是在示例2中,光看Html标签就知道这个页面是在展示班级信息,班级信息中还有班主任的信息和所有学生的信息。

 

另外,示例1中,若一个班级的学生有30个,学生信息的Html会出现30次,如果将来发生变动,这30出学生信息的代码都需要改动。

 

 

 

制作一个属于自己的Directive

示例3:

 

 1 <!DOCTYPE>

 2 <html>

 3 <head>

 4     <script src="/Scripts/Angular.js"></script>

 5     <script type="text/javascript">

 6         (function () {

 7             VAR app = Angular.module(&#39;ngCustomDirectivetest', []);

 8             app.controller('myController', ['$scope', function ($scope) {

 9                 $scope.info = {

10                     yourname: 'Jack',

11                     template: 'template.html'

12                 };

13             }]);

14 

15             // 自定义Element的Directive

16             app.directive("studentInfo", function () {

17                 return {

18                     // A 代表 Attribute

19                     // C 代表 Class

20                     // E 代表 Element

21                     // ACE 表示同时创建 A、C、E 三种

22                     restrict: 'ACE',

23                     // templateUrl 指向独立的Html文件,AngularJS会用Html文件中的内容替换studentInfo对象

24                     templateUrl: 'template.html'

25                 };

26             });

27         })();

28     </script>

29 </head>

30 <body ng-app="ngCustomDirectiveTest">

31     <p ng-controller="myController as myCtrl">

32         <student-info></student-info>

33         <br />

34         <data-student-info></data-student-info>

35         <br />

36 

37         <p student-info></p>

38         <br />

39         <p data_student-info></p>

40         <br />

41 

42         <p class="student-info"></p>

43         <br />

44         <p class="data-student-info"></p>

45         <br />

46     </p>

47 </body>

48 </html>

 

template.html:

 

1 <p>

2     <p>This is a custom template.</p>

3     <p>Your name: {{info.yourname}}</p>

4 </p>

注意:你可能还见过restrict:'M',或者Directive的命名以PRe_suf、pre:suf这样的代码书写方式,这些都已经“过时”了,最潮的restrict仅使用ACE三种,命名方式使用pre-suf。

 

另外,你可能疑惑,为什么加上"data-"前缀的为什么也能被解析?实际上AngularJS在处理Directive时,首先会忽略Directive命名中的"data-"或者"x-"前缀,因此无论你加上"data-"还是"x-",AngularJS还是能正确解析的,不过"x-"也是一种过时的写法,我们可以忽略。

 

 

 

好了,是不是很容易?属于我们自己的Directive就这样创建成功了,接着让我们更深入一些,看一下Directive的scope属性。首先看一下以下3段代码:

 

示例4(student-info直接使用了包含它的Controller的Scope中的变量jack和alice):

 

 

 1 <!DOCTYPE>

 2 <html>

 3 <head>

 4     <script src="/Scripts/angular.js"></script>

 5     <script type="text/javascript">

 6         (function () {

 7             var app = angular.module('ngCustomDirectiveTest', []);

 8             app.controller('myController', ['$scope', function ($scope) {

 9                 $scope.jack = {

10                     name: 'Jack',

11                     sex: 'Male'

12                 },

13                 $scope.alice = {

14                     name: 'Alice',

15                     sex: 'Female'

16                 }

17             }]);

18 

19             app.directive("studentInfo", function () {

20                 return {

21                     restrict: 'E',

22                     template: '<p><p>Student name: {{jack.name}}</p><p>Student sex: {{jack.sex}}</p></p><br /><p><p>Student name: {{alice.name}}</p><p>Student sex: {{alice.sex}}</p></p>'

23                 };

24             });

25         })();

26     </script>

27 </head>

28 <body ng-app="ngCustomDirectiveTest">

29     <p ng-controller="myController as myCtrl">

30         <student-info></student-info>

31     </p>

32 </body>

33 </html>

 

示例5(和示例1类似,直接使用包含student-info的Controller中的变量students,在template中使用ng-repeat展示学生信息):

 

 

 1 <!DOCTYPE>

 2 <html>

 3 <head>

 4     <script src="/Scripts/angular.js"></script>

 5     <script type="text/javascript">

 6         (function () {

 7             var app = angular.module('ngCustomDirectiveTest', []);

 8             app.controller('myController', ['$scope', function ($scope) {

 9                 $scope.students = [

10                     {

11                         name: 'Jack',

12                         sex: 'Male'

13                     },

14                     {

15                         name: 'Alice',

16                         sex: 'Female'

17                     }

18                 ];

19             }]);

20 

21             app.directive("studentInfo", function () {

22                 return {

23                     restrict: 'E',

24                     template: '<p ng-repeat="stu in students"><p>Student name:{{stu.name}}</p><p>Student sex:{{stu.sex}}</p></p>'

25                 };

26             });

27         })();

28     </script>

29 </head>

30 <body ng-app="ngCustomDirectiveTest">

31     <p ng-controller="myController as myCtrl">

32         <student-info></student-info>

33     </p>

34 </body>

35 </html>

 

示例6(定义两个不同的Controller:jackController和aliceController,使student-info处于2个不同的controller中):

 

 

 1 <!DOCTYPE>

 2 <html>

 3 <head>

 4     <script src="/Scripts/angular.js"></script>

 5     <script type="text/javascript">

 6         (function () {

 7             var app = angular.module('ngCustomDirectiveTest', []);

 8             app.controller('jackController', ['$scope', function ($scope) {

 9                 $scope.student =

10                     {

11                         name: 'Jack',

12                         sex: 'Male'

13                     }

14             }]);

15 

16             app.controller('aliceController', ['$scope', function ($scope) {

17                 $scope.student =

18                     {

19                         name: 'Alice',

20                         sex: 'Female'

21                     }

22             }]);

23 

24             app.directive("studentInfo", function () {

25                 return {

26                     restrict: 'E',

27                     template: '<p><p>Student name:{{student.name}}</p><p>Student sex:{{student.sex}}</p></p>'

28                 };

29             });

30         })();

31     </script>

32 </head>

33 <body ng-app="ngCustomDirectiveTest">

34     <p ng-controller="jackController as jackCtrl">

35         <student-info></student-info>

36     </p>

37     <br />

38     <p ng-controller="aliceController as aliceCtrl">

39         <student-info></student-info>

40     </p>

41 </body>

42 </html>

 

 

 

 上述三种方式,都能达到我们所需的目的:自定义一个名为student-info的Directive,展示Controller中的学生信息。但仔细分析上述3种不同的代码,能发现它们各自有不同的问题:

 

1. 示例4中,student-info的template中的所有表达式严重依赖Controller中的变量定义,导致student-info无法抽象成一个公共的学生信息展示模块。

 

2. 示例5中,虽然使用ng-repeat封装了代码,但是还是存在依赖Controller中students变量的问题,示例5仅比示例4稍微好点。

 

3. 示例6中,定义了不同的Controller来隔离作用域,但N个学生需要定义N个作用域,并且定义Controller时,还是必须定义一个名为student的变量,否则代码无法正确执行,因此还是存在耦合性。

 

 

 

 好吧,让我们看看AngularJS为我们提供的优雅的解决方案-Isolate scope:

 

示例7(通过使用=attr将Isolate scope中的属性赋值给Directive的名为'attr'的Attribute):

 

 

 1 <!DOCTYPE>

 2 <html>

 3 <head>

 4     <script src="/Scripts/angular.js"></script>

 5     <script type="text/javascript">

 6         (function () {

 7             var app = angular.module('ngCustomDirectiveTest', []);

 8             app.controller('myController', ['$scope', function ($scope) {

 9                 $scope.jack = {

10                     name: 'Jack',

11                     sex: 'Male'

12                 },

13                 $scope.alice = {

14                     name: 'Alice',

15                     sex: 'Female'

16                 }

17             }]);

18 

19             app.directive("studentInfo", function () {

20                 return {

21                     restrict: 'E',

22                     // 定义student-info的Isolate scope

23                     scope: {

24                         // 作用域内定义一个变量:newNameinScope

25                         // 值对应到Directive中的info属性

26                         newNameInScope: '=info'

27                     },

28                     // template 不再依赖外部, 仅依赖内部的newNameInScope变量

29                     template: '<p><p>Student name: {{newNameInScope.name}}</p><p>Student sex: {{newNameInScope.sex}}</p></p>'

30                 };

31             });

32         })();

33     </script>

34 </head>

35 <body ng-app="ngCustomDirectiveTest">

36     <p ng-controller="myController as myCtrl">

37         <!--将myController中的jack属性传递给info-->

38         <student-info info="jack"></student-info>

39         <br />

40         <!--将myController中的alice属性传递给info-->

41         <student-info info="alice"></student-info>

42     </p>

43 </body>

44 </html>

 

 

 

 不同之处已经在注释中说明,示例7已经完全将student-info与外界隔离,不在存在耦合性,真正达到了我们自定义Directive的目的2(见本文"什么时候需要自定义Directive"部分)。

 

 让我们再对示例7进行一些调整

 

 示例8:

 

 

 1 <!DOCTYPE>

 2 <html>

 3 <head>

 4     <script src="/Scripts/angular.js"></script>

 5     <script type="text/javascript">

 6         (function () {

 7             var app = angular.module('ngCustomDirectiveTest', []);

 8             app.controller('myController', ['$scope', function ($scope) {

 9                 $scope.jack = {

10                     name: 'Jack',

11                     sex: 'Male'

12                 },

13                 $scope.alice = {

14                     name: 'Alice',

15                     sex: 'Female'

16                 }

17             }]);

18 

19             app.directive("studentInfo", function () {

20                 return {

21                     restrict: 'E',

22                     scope: {

23                         newNameInScope: '=info'

24                     },

25                     // 这里的alice将不能获取Controller中的变量alice的信息

26                     template: '<p><p>Student name: {{newNameInScope.name}}</p><p>Student sex: {{newNameInScope.sex}}</p><br /><p>DeskMATE name: {{alice.name}}</p><p>Deskmate sex: {{alice.sex}}</p></p>'

27                 };

28             });

29         })();

30     </script>

31 </head>

32 <body ng-app="ngCustomDirectiveTest">

33     <p ng-controller="myController as myCtrl">

34         <student-info info="jack"></student-info>

35     </p>

36 </body>

37 </html>

 

 

 

 这个就是所谓的封闭(Isolate),对比一下示例4,当创建student-info时指定了scope属性后,不在scope中指定的变量,在student-info中将无法被识别,做到了“封闭”。这样,当你定义一个公共模块时,不会因为在不同的Controller中使用而产生意想不到的问题。因此当你需要定义一个具有隔离性的Directive时,即使不需要传递Controller中的变量,也务必加上scope属性。

 

 不过我们只能将一个字符串或者一个对象传入Isolate scope中,试想若遇到某些特殊情况,需要直接包含指定的Html片段时怎么办?AngularJS也是有这样的功能的。

 

示例9:

 

 

 1 <!DOCTYPE>

 2 <html>

 3 <head>

 4     <script src="/Scripts/angular.js"></script>

 5     <script type="text/javascript">

 6         (function () {

 7             var app = angular.module('ngCustomDirectiveTest', []);

 8             app.controller('myController', ['$scope', function ($scope) {

 9                 $scope.jack = {

10                     name: 'Jack',

11                     sex: 'Male'

12                 },

13                 $scope.alice = {

14                     name: 'Alice',

15                     sex: 'Female'

16                 }

17             }]);

18 

19             app.directive("studentInfo", function () {

20                 return {

21                     restrict: 'E',

22                     // 指定transclude属性为true

23                     transclude: true

24                 };

25             });

26         })();

27     </script>

28 </head>

29 <body ng-app="ngCustomDirectiveTest">

30     <p ng-controller="myController as myCtrl">

31         <!--指明student-info将会使用transclude模式-->

32         <student-info ng-transclude>

33             <!-- student-info的内容由使用者自己指定,并且内容中能访问student-info的scope以外的变量 -->

34             <p>Student name: {{jack.name}}</p>

35             <p>Student sex: {{jack.sex}}</p>

36             <br />

37             <p>Deskmate name: {{alice.name}}</p>

38             <p>Deskmate sex: {{alice.sex}}

39         </student-info>

40     </p>

41 </body>

42 </html>

 

 

 

其他自定义Directive的示例

示例10(自定义Directive操作DOM,官方文档中的demo):

 

 

 1 <!DOCTYPE>

 2 <html>

 3 <head>

 4     <script src="/Scripts/angular.js"></script>

 5     <script type="text/javascript">

 6         (function () {

 7             var app = angular.module('docsTimeDirective', []);

 8 

 9             app.controller('Controller', ['$scope', function ($scope) {

10                 $scope.format = 'M/d/yy h:mm:ss a';

11             }])

12 

13             app.directive('mycurrentTime', ['$interval', 'dateFilter', function ($interval, dateFilter) {

14                 function link(scope, element, attrs) {

15                     var format,

16                         timeoutId;

17 

18                     function updateTime() {

19                         element.text(dateFilter(new Date(), format));

20                     }

21 

22                     scope.$watch(attrs.myCurrentTime, function (value) {

23                         format = value;

24                         updateTime();

25                     });

26 

27                     element.on('$destroy', function () {

28                         $interval.cancel(timeoutId);

29                     });

30 

31                     timeoutId = $interval(function () {

32                         updateTime();

33                     }, 1000);

34                 }

35 

36                 return {

37                     link: link

38                 };

39             }]);

40         })();

41     </script>

42 </head>

43 <body ng-app="docsTimeDirective">

44     <p ng-controller="Controller">

45         Date format:

46         <input ng-model="format">

47         <hr />

48         Current time is: <span my-current-time="format"></span>

49     </p>

50 </body>

51 </html>

 

如果想要使Directive改变DOM,一般会用到link参数,其原型为:function link(scope, element, attrs) {...}:

 

scope: 与当前元素结合的scope

elment:当前元素

$attrs:当前元素的属性对象

 

 

示例11(通过使用&attr开放Directive,将自定义的方法绑定到Directive上):

 

 

 1 <!DOCTYPE>

 2 <html>

 3 <head>

 4     <script src="/Scripts/angular.js"></script>

 5     <script type="text/javascript">

 6         (function () {

 7             var app = angular.module('isoFnBindTest', []);

 8 

 9             app.controller('myController', ['$scope', function ($scope) {

10                 $scope.name = '';

11                 $scope.message = '';

12                 $scope.isHide = true;

13                 $scope.sayHello = function (message, name) {

14                     $scope.isHide = false;

15                     $scope.name = name;

16                     $scope.message = message;

17                     alert($scope.message + ',' + $scope.name);

18                 };

19             }]);

20 

21             app.directive('myGreeting', function () {

22                 return {

23                     restrict: 'E',

24                     transclude: true,

25                     scope: {

26                         // Step 2: greet方法绑定到onGreet属性(对应Html中的on-greet),并将greet的输入参数传给onGreet

27                         'greet': '&onGreet'

28                     },

29                     templateUrl: 'my-greeting.html'

30                 };

31             });

32         })();

33     </script>

34 </head>

35 <body ng-app="isoFnBindTest">

36     <p ng-controller="myController">

37         <!-- Step 3: on-greet指向了myController中的sayHello方法,此时on-greet中能直接访问到greet的输入参数-->

38         <my-greeting on-greet="sayHello(message, name)">

39             <p ng-hide="isHide">

40                 {{message}}, {{name}}!

41             </p>

42         </my-greeting>

43     </p>

44 </body>

45 </html>

 

my-greeting.html:

 

1 <p>

2   <!-- Step1: 一旦触发click, 将调用Isolate scope中的greet方法-->

3   <button ng-click="greet({message: 'Hello', name: 'Tom'})">Click me!</button>

4   <p ng-transclude></p>

5 </p>

 

 

示例12(Directive侦听事件,官方Demo):

 

 

 1 <!DOCTYPE>

 2 <html>

 3 <head>

 4     <script src="/Scripts/angular.js"></script>

 5     <script type="text/javascript">

 6         (function () {

 7             var app = angular.module('DragModule', []);

 8 

 9             app.directive('myDraggable', ['$document', function ($document) {

10                 return {

11                     link: function (scope, element, attr) {

12                         var startX = 0, startY = 0, x = 0, y = 0;

13 

14                         element.css({

15                             position: 'relative',

16                             border: '1px solid red',

17                             backgroundColor: 'lightgrey',

18                             cursor: 'pointer'

19                         });

20 

21                         element.on('mousedown', function (event) {

22                             // Prevent default dragging of selected content

23                             event.preventDefault();

24                             startX = event.pageX - x;

25                             startY = event.pageY - y;

26                             $document.on('mouSEMove', mousemove);

27                             $document.on('mouseup', mouseup);

28                         });

29 

30                         function mousemove(event) {

31                             y = event.pageY - startY;

32                             x = event.pageX - startX;

33                             element.css({

34                                 top: y + 'px',

35                                 left: x + 'px'

36                             });

37                         }

38 

39                         function mouseup() {

40                             $document.off('mousemove', mousemove);

41                             $document.off('mouseup', mouseup);

42                         }

43                     }

44                 };

45             }]);

46         })();

47     </script>

48 </head>

49 <body ng-app="dragModule">

50     <span my-draggable>Drag ME</span>

51 </body>

52 </html>

 

 

示例13(Directive之间的相互作用,官方Demo):

 

 

 1 <!DOCTYPE>

 2 <html>

 3 <head>

 4     <script src="/Scripts/angular.js"></script>

 5     <script type="text/javascript">

 6         (function () {

 7             var app = angular.module('docsTabsExample', []);

 8 

 9             app.directive('myTabs', function () {

10                 return {

11                     restrict: 'E',

12                     transclude: true,

13                     scope: {},

14                     controller: function ($scope) {

15                         var panes = $scope.panes = [];

16 

17                         $scope.select = function (pane) {

18                             angular.forEach(panes, function (pane) {

19                                 pane.selected = false;

20                             });

21                             pane.selected = true;

22                         };

23 

24                         this.addPane = function (pane) {

25                             if (panes.length === 0) {

26                                 $scope.select(pane);

27                             }

28                             panes.push(pane);

29                         };

30                     },

31                     templateUrl: 'my-tabs.html'

32                 };

33             });

34 

35             app.directive('myPane', function () {

36                 return {

37                     // 指定必须有myTabs对象,若对象不存在则会报错,见下面的图1

38                     require: '^myTabs',  // ^ 表示将在父级的范围内查找该对象, 没有 ^ 表示在Directive内查找该对象, 若范围指定错误无法找到myTabs,js则会报错

39                     restrict: 'E',

40                     transclude: true,

41                     scope: {

42                         title: '@'

43                     },

44                     link: function (scope, element, attrs, tabsCtrl) {

45                         tabsCtrl.addPane(scope);

46                     },

47                     templateUrl: 'my-pane.html'

48                 };

49             });

50         })();

51     </script>

52 </head>

53 <body ng-app="docsTabsExample">

54     <my-tabs>

55       <my-pane title="Hello">

56         <h4>Hello</h4>

57         <p>Lorem ipsum dolor sit amet</p>

58       </my-pane>

59       <my-pane title="World">

60         <h4>World</h4>

61         <em>Mauris elementum elementum enim at suscipit.</em>

62         <p><a href ng-click="i = i + 1">counter: {{i || 0}}</a></p>

63       </my-pane>

64     </my-tabs>

65 </body>

66 </html>

 

my-tabs.html:

 

 

1 <p class="tabbable">

2   <ul class="nav nav-tabs">

3     <li ng-repeat="pane in panes" ng-class="{active:pane.selected}">

4       <a href="" ng-click="select(pane)">{{pane.title}}</a>

5     </li>

6   </ul>

7   <p class="tab-content" ng-transclude></p>

8 </p>

 

my-pane.html:

 

1 <p class="tab-pane" ng-show="selected" ng-transclude>

2 </p>

 

觉得可用,就经常来吧! 脚本宝典 欢迎评论哦! js脚本,巧夺天工,精雕玉琢。小宝典献丑了!

脚本宝典总结

以上是脚本宝典为你收集整理的javascript代码实例教程-AngularJS自定义Directive全部内容,希望文章能够帮你解决javascript代码实例教程-AngularJS自定义Directive所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。