跟我学AngularJs:Directive指令用法解读(上)
林炳文Evankaka原创作品。转载请注明出处http://www.52php.cn/tag/http://blog.csdn.net/evankaka 本教程使用AngularJs版本:1.5.3 AngularJs GitHub:https://github.com/angular/angular.js/ AngularJs下载地址:https://angularjs.org/ 摘要: Directive(指令)笔者认为是AngularJ非常强大而有有用的功能之一。它就相当于为我们写了公共的自定义DOM元素或CLASS属性或ATTR属性,并且它不只是单单如此,你还可以在它的基础上来操作scope、绑定事件、更改样式等。通过这个Directive,我们可以封装很多公共指令,比如分页指令、自动补全指令等等。然后在HTML页面里只需要简单的写一行代码就可以实现很多强大的功能。一般情况下,需要用Directive有下面的情景: 1. 使你的Html更具语义化,不需要深入研究代码和逻辑即可知道页面的大致逻辑。 一、Directive的定义及其使用方法 AngularJs的指令定义大致如下 angular.module("app",[]).directive("directiveName",function(){ return{ //通过设置项来定义 }; }) Directive可以放置于元素名、属性、class、注释中。下面是引用myDir这个directive的等价方式。(但很多directive都限制为“属性”的使用方式) <span directive-name="exp"></span>//属性 <span class="directive-name: exp;"></span>//class <directive-name></directive-name>//元素 <!-- directive: directive-name exp -->//注释 如下一个实例 : <!DOCTYPE html> <html lang="zh" ng-app="myApp"> <head> <meta charset="UTF-8"> <title>AngularJS入门学习</title> <script type="text/javascript" src="./1.5.3/angular.min.js"></script> </head> <body> <hello-world></hello-world> </body> <script type="text/javascript"> var app = angular.module('myApp',[]); app.directive('helloWorld',function() { return { restrict: 'E',template: '<div>Hi 我是林炳文~~~</div>',replace: true }; }); </script> </html>结果: 下面是一个directive的详细版 var myModule = angular.module(...); myModule.directive('directiveName',function factory(injectables) { var directiveDefinitionObject = { priority: 0, template: '<div></div>', templateUrl: 'directive.html', replace: false, transclude: false, restrict: 'A', scope: false, compile: function compile(tElement,tAttrs,transclude) { return { pre: function preLink(scope,iElement,iAttrs,controller) { ... }, post: function postLink(scope,controller) { ... } } }, link: function postLink(scope,iAttrs) { ... } }; return directiveDefinitionObject; }); 二、Directive指令内容解读 可 以看到它有8个内容 1.restrict(字符串)可选参数,指明指令在DOM里面以什么形式被声明;取值有:E(元素),A(属性),C(类),M(注释),其中默认值为A;当然也可以两个一起用,比如EA.表示即可以是元素也可以是属性。 E(元素):<directiveName></directiveName> A(属性):<div directiveName='expression'></div> C(类): <div class='directiveName'></div> M(注释):<--directive:directiveName expression-->
一般情况下E/A/C用得比较多。
2.priority (数字),可选参数,指明指令的优先级,若在单个DOM上有多个指令,则优先级高的先执行; 3.terminal (布尔型),可选参数,可以被设置为true或false,若设置为true,则优先级低于此指令的其他指令则无效,不会被调用(优先级相同的还是会执行) 4.template(字符串或者函数)可选参数,可以是: (1)一段HTML文本 <!DOCTYPE html> <html lang="zh" ng-app="myApp"> <head> <meta charset="UTF-8"> <title>AngularJS入门学习</title> <script type="text/javascript" src="./1.5.3/angular.min.js"></script> </head> <body> <hello-world></hello-world> </body> <script type="text/javascript"> var app = angular.module('myApp',template: '<div><h1>Hi 我是林炳文~~~</h1></div>',replace: true }; }); </script> </html> (2)一个函数,可接受两个参数tElement和tAttrs 其中tElement是指使用此指令的元素,而tAttrs则实例的属性,它是一个由元素上所有的属性组成的集合(对象)形如: <hello-world2 title = '我是第二个directive'></hello-world2> 其中title就是tattrs上的属性 下面让我们看看template是一个函数时候的情况 <!DOCTYPE html> <html lang="zh" ng-app="myApp"> <head> <meta charset="UTF-8"> <title>AngularJS入门学习</title> <script type="text/javascript" src="./1.5.3/angular.min.js"></script> </head> <body> <hello-world></hello-world> <hello-world2 title = '我是第二个directive'></hello-world2> </body> <script type="text/javascript"> var app = angular.module('myApp',replace: true }; }); app.directive("helloWorld2",function(){ return{ restrict:'EAC',template: function(tElement,tAttrs){ var _html = ''; _html += '<div>' +'hello '+tAttrs.title+'</div>'; return _html; } }; }); </script> </html>结果: 可以看到指令中还用到了hello-world2中的标签中的 title字段
5.templateUrl(字符串或者函数),可选参数,可以是
(1)一个代表HTML文件路径的字符串 (2)一个函数,可接受两个参数tElement和tAttrs(大致同上)
注意:在本地开发时候,需要运行一个服务器,不然使用templateUrl会报错Cross Origin Request Script(CORS)错误。由于加载html模板是通过异步加载的,若加载大量的模板会拖慢网站的速度,这里有个技巧,就是先缓存模板
你可以再你的index页面加载好的,将下列代码作为你页面的一部分包含在里面。 <script type='text/ng-template' id='hello.html'> <div><h1>Hi 我是林炳文~~~</h1></div> </script> 这里的id属性就是被设置在templateUrl上用的。 <!DOCTYPE html> <html lang="zh" ng-app="myApp"> <head> <meta charset="UTF-8"> <title>AngularJS入门学习</title> <script type="text/javascript" src="./1.5.3/angular.min.js"></script> </head> <body> <hello-world></hello-world> </body> <script type="text/javascript"> var app = angular.module('myApp',templateUrl: 'hello.html',replace: true }; }); </script> <script type='text/ng-template' id='hello.html'> <div><h1>Hi 我是林炳文~~~</h1></div> </script> </html> 输出结果: 另一种办法缓存是: app.run(["$templateCache",function($templateCache) { $templateCache.put("hello.html","<div><h1>Hi 我是林炳文~~~</h1></div>"); }]); 使用实例如下: <!DOCTYPE html> <html lang="zh" ng-app="myApp"> <head> <meta charset="UTF-8"> <title>AngularJS入门学习</title> <script type="text/javascript" src="./1.5.3/angular.min.js"></script> </head> <body> <hello-world></hello-world> </body> <script type="text/javascript"> var app = angular.module('myApp',replace: true }; }); app.run(["$templateCache","<div><h1>Hi 我是林炳文~~~</h1></div>"); }]); </script> </html> 结果: 其实第一种方法还好一些,写起来会比较快,笔者就得最多的也是第一种写法,直接包在scprit当中
6.replace
(布尔值),默认值为false,设置为true时候,我们再来看看下面的例子(对比下在template时候举的例子) replace为true时,hello-world这个标签不在了,反之,则存在。
7.scope
(1)默认值false。表示继承父作用域; (2)true。表示继承父作用域,并创建自己的作用域(子作用域); (3){}。表示创建一个全新的隔离作用域;
7.1首先我们先来了解下scope的继承机制。我们用ng-controller这个指令举例,
<!DOCTYPE html> <html lang="zh" ng-app="myApp"> <head> <meta charset="UTF-8"> <title>AngularJS入门学习</title> <script type="text/javascript" src="./1.5.3/angular.min.js"></script> </head> <body> <div ng-controller='MainController'> 父亲:{{name}}<input ng-model="name" /> <div my-directive></div> </div> </body> <script type="text/javascript"> var app = angular.module('myApp',[]); app.controller('MainController',function ($scope) { $scope.name = '林炳文'; }); app.directive('myDirective',function () { return { restrict: 'EA',scope:false,template: '<div>儿子:{{ name }}<input ng-model="name"/></div>' }; }); </script> </html> 接下来我们通过一个简单明了的例子来说明scope取值不同的差别: scope:false scope:true scope:{} 当为false时候,儿子继承父亲的值,改变父亲的值,儿子的值也随之变化,反之亦如此。(继承不隔离) 当为true时候,儿子继承父亲的值,改变父亲的值,儿子的值随之变化,但是改变儿子的值,父亲的值不变。(继承隔离) 当为{}时候,没有继承父亲的值,所以儿子的值为空,改变任何一方的值均不能影响另一方的值。(不继承隔离)
tip:当你想要创建一个可重用的组件时隔离作用域是一个很好的选择,通过隔离作用域我们确保指令是‘独立’的,并可以轻松地插入到任何HTML app中,并且这种做法防止了父作用域被污染;
7.2隔离作用域可以通过绑定策略来访问父作用域的属性。
directive 在使用隔离 scope 的时候,提供了三种方法同隔离之外的地方交互。这三种分别是
@ 局部 scope 属性 @ 方式局部属性用来访问 directive 外部环境定义的字符串值,主要是通过 directive 所在的标签属性绑定外部字符串值。这种绑定是单向的,即父 scope 的绑定变化,directive 中的 scope 的属性会同步变化,而隔离 scope 中的绑定变化,父 scope 是不知道的。 如下示例:directive 声明未隔离 scope 类型,并且使用@绑定 name 属性,在 directive 中使用 name 属性绑定父 scope 中的属性。当改变父 scope 中属性的值的时候,directive 会同步更新值,当改变 directive 的 scope 的属性值时,父 scope 无法同步更新值。 js 代码: <!DOCTYPE html> <html lang="zh" ng-app="myApp"> <head> <meta charset="UTF-8"> <title>AngularJS入门学习</title> <script type="text/javascript" src="./1.5.3/angular.min.js"></script> </head> <body> <div ng-controller="myController"> <div class="result"> <div>父scope: <div>Say:{{name}}<br>改变父scope的name:<input type="text" value="" ng-model="name"/></div> </div> <div>隔离scope: <div isolated-directive name="{{name}}"></div> </div> <div>隔离scope(不使用父scope {{name}}): <div isolated-directive name="name"></div> </div> </div> </body> <script type="text/javascript"> var app = angular.module('myApp',[]); app.controller("myController",function ($scope) { $scope.name = "hello world"; }).directive("isolatedDirective",function () { return { scope: { name: "@" },template: 'Say:{{name}} <br>改变隔离scope的name:<input type="buttom" value="" ng-model="name" class="ng-pristine ng-valid">' }; }); </script> </html>结果:页面初始效果 可以看到父scope上的内容发生改变,子scope同时发生改变。而子scope上的内容发生改变。不影响父scope上的内容! = 局部 scope 属性 = 通过 directive 的 attr 属性的值在局部 scope 的属性和父 scope 属性名之间建立双向绑定。 示例代码: <!DOCTYPE html> <html lang="zh" ng-app="myApp"> <head> <meta charset="UTF-8"> <title>AngularJS入门学习</title> <script type="text/javascript" src="./1.5.3/angular.min.js"></script> </head> <body> <div ng-controller="myController"> <div>父scope: <div>Say:{{user.name}}<br>改变父scope的name:<input type="text" value="" ng-model="userBase.name"/></div> </div> <div>隔离scope: <div isolated-directive user="userBase"></div> </div> </div> </body> <script type="text/javascript"> var app = angular.module('myApp',function ($scope) { $scope.userBase = { name: 'hello',id: 1 }; }).directive("isolatedDirective",function () { return { scope: { user: "=" },template: 'Say:{{user.name}} <br>改变隔离scope的name:<input type="buttom" value="" ng-model="user.name"/>' } }) </script> </html>效果: & 局部 scope 属性 & 方式提供一种途经是 directive 能在父 scope 的上下文中执行一个表达式。此表达式可以是一个 function。 如下示例在 directive 中执行父 scope 的 function。 <!DOCTYPE html> <html lang="zh" ng-app="myApp"> <head> <meta charset="UTF-8"> <title>AngularJS入门学习</title> <script type="text/javascript" src="./1.5.3/angular.min.js"></script> </head> <body> <div ng-controller="myController"> <div>父scope: <div>Say:{{value}}</div> </div> <div>隔离scope: <div isolated-directive action="click()"></div> </div> </div> </body> <script type="text/javascript"> var app = angular.module('myApp',function ($scope) { $scope.value = "hello world"; $scope.click = function () { $scope.value = Math.random(); }; }).directive("isolatedDirective",function () { return { scope: { action: "&" },template: '<input type="button" value="在directive中执行父scope定义的方法" ng-click="action()"/>' } }) </script> </html>效果:
指令的内容比较多,下一章节再来讲讲transclude、compline、link、contrller
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |