Angular之指令Directive用法详解
项目筹备近期开启angular学习,指令比较难理解所以记录备案,推荐视频大漠穷秋 angular实战 由于篇幅过长,列举大纲如下:
一、指令directive概述
指令可以对元素绑定事件监听或者改变dom结构而使html拥有像jquery一样效果具有交互性。不同于jquery,angular设计核心思想是通过数据与模板的绑定,摆脱繁琐的dom操作,而将注意力集中在业务逻辑上。
几种常见指令ng-app 指令用来指定ng的作用域是在那个标签以内部分(<html ng-app="myapp">标签) ng-repeat迭代器指令可以重复标记元素、ng-show指令可以根据条件是否显示一个元素、ng-model指令具有双向数据绑定特性、ng-controller 用来声明一个需要和数据进行绑定的模板区域
二、自定义指令directive之模式匹配restrict
直接上代码体验一把,index.html
<!doctype html> <html ng-app="mymodule"> <head> <meta charset="utf-8"> <title>angular指令--自定义标签</title> <script type="text/javascript" src="framework/1.3.0.14/angular.js"></script> </head> <body> <hello></hello> <div hello></div> <div class='hello'></div> <!-- directive:hello --> <div></div> <!--代码模板template--> <script type="text/ng-template" id="hello_angular.html"> <p>hello angular</p> </script> <!--代码模板template--> </body> </html>
指令directive.js
<script type="text/javascript"> //调用angular对象的module方法来声明一个模块,模块的名字和ng-app的值对应 var mymodule = angular.module('mymodule',[]); /* restrict 属性值说明 <推荐使用ea> * e--element元素 <hello></hello> * a--attribute 属性 <div hello></div> * c-class 样式类 <div class="hello"></div> * m 注释 <!-- directive:hello --> */ //指令--对元素绑定事件监听或者改变dom mymodule.directive('hello', function(){ return { restrict: 'eacm', templateurl:'hello_angular.html', /*template : '<p>hello angular</p>',*/ replace: true } }) </script>
==========================================================
restrict---匹配模式说明, 英文意思是"限制;约束;限定",这里指的是匹配我自定义的标签
==========================================================
•e 元素(element) <hello></hello>
•a 属性(attribute) <div hello></div>
•c 样式类(class) <div class="hello"></div>
•m 注释 <!-- directive:hello --> 注意!!!空格(不常用)
温馨tips: 推荐使用ec或ea匹配模式
replace 是否替换元素的模式 replace:true浏览器dom结构如下
replace:false 或没有replace属性时浏览器dom结构如下
三、指令之嵌套变换transclude
<!doctype html> <html ng-app="myapp"> <head> <meta charset="utf-8"> <title>transclude 嵌套变换</title> <script type="text/javascript" src="framework/1.3.0.14/angular.js"></script> </head> <body> <hello>这里是内容哦.....</hello> <div hello>这里是内容哦hello....</div> <script type="text/javascript"> var myapp = angular.module('myapp', []); myapp.directive('hello',function(){ return { restrict: 'ea', template: '<p>hello world!!!<b ng-transclude></b></p>', transclude: true, /*嵌套变换*/ replace: true /*替换*/ } }) </script> </body> </html>
四、指令directive运行原理
五、指令配置参数说明
mymodule.directive('namespacedirectivename', function factory(injectables) { var directivedefinitionobject = { restrict: string,//指令的使用方式,包括标签,属性,类,注释 priority: number,//指令执行的优先级 template: string,//指令使用的模板,用html字符串的形式表示 templateurl: string,//从指定的url地址加载模板或<script type="text/ng-template" id="string"></script> replace: bool,//是否用模板替换当前元素,若为false,则append在当前元素上 transclude: bool,//是否将当前元素的内容转移到模板中 scope: bool or object,//指定指令的作用域 controller: function controllerconstructor($scope, $element, $attrs, $transclude){...},//定义与其他指令进行交互的接口函数 require: string,//指定需要依赖的其他指令 link: function postlink(scope, ielement, iattrs) {...},//以编程的方式操作dom,包括添加监听器等 compile: function compile(telement, tattrs, transclude){ return: { pre: function prelink(scope, ielement, iattrs, controller){...}, post: function postlink(scope, ielement, iattrs, controller){...} } }//编程的方式修改dom模板的副本,可以返回链接函数 }; return directivedefinitionobject; });
六、指令与控制器的交互
index.html 如下
<!doctype html> <html ng-app="myapp"> <head> <meta charset="utf-8"> <title>directive指令与controller控制器交互</title> <!--引入js库anglarjs--> <script type="text/javascript" src="framework/1.3.0.14/angular.js"></script> <script type="text/javascript" src="js/directive&controller.js"></script> </head> <body> <div ng-controller="myappctrl"> <loader hello howtoload="loaddata()">数据加载......</loader> </div> <div ng-controller="myappctrl2"> <loader hello howtoload="loaddata2()">数据加载2......</loader> </div> </body> </html>
directive&controller.js
var myapp = angular.module('myapp', []); myapp.controller('myappctrl', ['$scope', function($scope){ console.log($scope); $scope.loaddata = function(){ console.log('数据加载中.....'); } }]); myapp.controller('myappctrl2', ['$scope', function($scope){ console.log($scope); $scope.loaddata2 = function(){ console.log('数据加载中2.....'); } }]); //指令与控制器之间交互 myapp.directive('loader', function(){ return { restrict: 'ea', template: '<div ng-transclude></div>', transclude: true, replace: true, /*scope: {}, 独立scope*/ link: function(scope, element, attrs){ element.bind('mouseenter', function(){ /*这里调用controller中的方法三种方式*/ /*(1) scope.loaddata(); (2) scope.$apply('loaddata()'); (3) attrs.howtoload === 属性上绑定的函数名称*/ //属性方式 注意坑!!! howtoload 得小写 scope.$apply(attrs.howtoload); }) } } })
实现的效果是当鼠标滑过div元素时,调用一个加载数据的方法。
上述例子中定义了两个控制器,然后两个控制器中都使用了loader指令,并且,每个指令中都有一个参数 howtoload .
关于指令中的 link ,上面介绍运行机制中可以了解到,link: function postlink(scope, element, attrs) {...}是用来操作dom和绑定监听事件的。
link中会有三个参数:scope(指令所属的控制器中的 $scope 对象)、element(指令所属dom元素)、attrs(dom元素所传的参数
如howtoload 参数给的值 loaddata()
然后对于如何调用所需函数,有两种方法:
1> scope.loaddata() 两个控制器方法不一致时,就不能用了
2> scope.$apply() $apply()方法会从所有控制器中找到多对应的方法。这就实现了指令的复用。
明确对于控制器ng-controller都会创建属于自己独立的scope;对于指令若无scope:{}声明会继承控制器中的scope
七、指令与指令的交互
index.html
<!doctype html> <html ng-app="mymodule"> <head> <meta charset="utf-8"> <title>directive指令与directive指令之间的交互</title> <!--引入第三方样式库bootstrap.min.css--> <link rel="stylesheet" href="framework/bootstrap-3.0.0/css/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" /> <!--引入js库anglarjs--> <script type="text/javascript" src="framework/1.3.0.14/angular.js"></script> <script type="text/javascript" src="js/directive&directive.js"></script> </head> <body> <div class="row"> <div class="col-md-3"> <superman strength>动感超人---力量</superman> </div> </div> <div class="row"> <div class="col-md-3"> <superman strength speed>动感超人2---力量+敏捷</superman> </div> </div> <div class="row"> <div class="col-md-3"> <superman strength speed light>动感超人3---力量+敏捷+发光</superman> </div> </div> </body> </html>
directive&directive.js
var mymodule = angular.module('mymodule',[]); //指令与指令之间交互 mymodule.directive('superman', function(){ return { scope: {},/*独立作用域*/ restrict: 'ae', template: '<button class="btn btn-primary" ng-transclude></button>', transclude: true, controller: function($scope){ /*暴露controller里面方法*/ $scope.abilities = []; this.addstrength = function(){ $scope.abilities.push('strength'); }; this.addspeed = function(){ $scope.abilities.push('speed'); }; this.addlight = function(){ $scope.abilities.push('light'); }; }, link: function(scope, element, attrs, supermanctr){ element.addclass = "btn btn-primary"; element.bind('mouseenter', function(){ console.log(scope.abilities); }) } } }) mymodule.directive('strength', function(){ return { require: "^superman",/*require参数指明需要依赖的指令*/ link: function(scope, element, attrs, supermanctr){ supermanctr.addstrength(); } } }); mymodule.directive('speed', function(){ return { require: "^superman", link: function(scope, element, attrs, supermanctr){ supermanctr.addspeed(); } } }); mymodule.directive('light', function(){ return { require: "^superman", link: function(scope, element, attrs, supermanctr){ supermanctr.addlight(); } } });
*require参数指明需要依赖的指令
*指令中的controller相当于暴露里面方法,便于指令复用
八、scope作用域绑定策略
scope “@” 把当前属性作为字符串传值
<!doctype html> <html ng-app="mymodule"> <head> <meta charset="utf-8"> <title>scope绑值策略一.'@'把当前属性作为字符串传值</title> <!--引入js库anglarjs--> <script type="text/javascript" src="framework/1.3.0.14/angular.js"></script> <script type="text/javascript" src="js/scope@.js"></script> </head> <body> <div ng-controller="myappctrl"> <drink flavor="{{ctrflavor}}"></drink> </div> </body> </html>
scope@.js
var mymodule = angular.module('mymodule', []); mymodule.controller('myappctrl',['$scope', function($scope){ console.log($scope); $scope.ctrflavor = "百事可乐"; }]); mymodule.directive('drink', function(){ return { restrict: 'ae', scope: { /*独立scope作用域*/ flavor: '@' }, replace:true, template: '<p>{{flavor}}</p>' //使用link进行指令和控制器两个作用域中数据的绑定。 //如果用scope中@的话,就不需要link这么麻烦了,angularjs会自动进行绑定 /*, link:function(scope,element,attrs){ element.bind('mouseenter', function(){ }) scope.flavor = attrs.flavor; }*/ } })
scope “=” 与父scope属性进行双向绑定
index.html
<!doctype html> <html ng-app="mymodule"> <head> <meta charset="utf-8"> <title>scope绑值策略二.'='与父scope中的属性进行双向绑定</title> <!--引入第三方样式库bootstrap.min.css--> <link rel="stylesheet" href="framework/bootstrap-3.0.0/css/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" /> <!--引入js库anglarjs--> <script type="text/javascript" src="js/scope=.js"></script> </head> <body> <div ng-controller="mymodulectrl" class="col-sm-6"> <p>{{describe}}</p> ctrl--控制器:<br /> <input type="text" ng-model="ctrflavor" class="form-control" /> <br /> <p>{{ctrflavor}}</p> directive--指令:<br /> <drink flavor="ctrflavor"></drink> <p>{{flavor}}</p> </div> </body> </html>
scope=.js
var mymodule = angular.module('mymodule', []); mymodule.controller('mymodulectrl',['$scope', function($scope){ $scope.describe = "scope绑值策略二.=与父scope中的属性进行双向绑定"; $scope.ctrflavor = "可口可乐"; }]); //=与父scope中的属性进行双向绑定 mymodule.directive('drink',function(){ return { restrict: 'ea', scope: { /*ng-isolate-scope 隔离作用域*/ flavor : '=' }, template: '<input type="text" class="form-control" ng-model="flavor" />' /*replace:true*/ } });
这个例子中有两个输入框,第一个绑定了mymodulectrl控制器中的scope对象的ctrlflavor 属性。
第二个绑定的是指令中的flavor属性。但是在drink 指令中 scope对象的flavor 属性 用了 ”=“ ,
与父scope中的属性进行双向数据绑定。所以两个值有一个改动,另一个属性值也会改动。 简单理解为把两个存放数据仓库给相等 a1 == b1
scope& '&'传递一个来自父scope的函数,稍后调用
index.html
<!doctype html> <html ng-app="mymodule"> <head> <meta charset="utf-8"> <title>scope绑值策略三.'&'传递一个来自父scope的函数,稍后调用</title> <!--引入第三方样式库bootstrap.min.css--> <link rel="stylesheet" href="framework/bootstrap-3.0.0/css/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" /> <!--引入js库anglarjs--> <script type="text/javascript" src="js/scope&.js"></script> </head> <body> <div ng-controller="mymodulectrl"> <greeting greet="sayhello(name)"></greeting> <greeting greet="sayhello(name)"></greeting> <greeting greet="sayhello(name)"></greeting> </div> <!--代码模板template--> <script type="text/ng-template" id="sayhello.html"> <div class="col-sm-12 container"> <form role = "form"> <div class = "form-group"> <input type="text" class="form-control" ng-model="username" /> <button class="btn btn-primary" ng-click="greet({name:username})">greeting</button> </div> </form> </div> </script> <!--代码模板template--> </body> </html>
scope&.js
var mymodule = angular.module('mymodule', []); mymodule.controller('mymodulectrl',['$scope', function($scope){ $scope.sayhello = function(name){ console.log('hello'+name); } }]); mymodule.directive('greeting', function(){ return { restrict: 'ea', scope: { /*'&'传递一个来自父scope的函数,稍后调用*/ greet : '&' }, templateurl: 'sayhello.html' } });
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
Angularjs使用directive自定义指令实现attribute继承的方法详解
-
vue.js内部自定义指令与全局自定义指令的实现详解(利用directive)
-
Angular.js中ng-include用法及多标签页面的实现方式详解
-
ES6新特性之模块Module用法详解
-
php设计模式之适配器模式原理、用法及注意事项详解
-
PHP设计模式之建造者模式(Builder)原理与用法案例详解
-
PHP设计模式之适配器模式(Adapter)原理与用法详解
-
linux命令之find命令的12个常用参数详解(含具体用法和注意事项)
-
android之camera用法实例详解
-
python爬虫之线程池和进程池功能与用法详解