Angular 指令
定义一个指令的方法非常简单,只需要调用 `directive` 方法即可:
- var app=angular.module('myapp',[]);
- app.directive(name,fn)
1. 基础指令
- var app = angular.module('myapp', []);
- app.run(function($templateCache) {
- $templateCache.put('cache', '<h3>模板内容来源于缓存</h3>')
- });
- app.directive('tsHello',
- function() {
- return {
- restrict: 'EAC',
- template: '<h3>Hello,directive</h3>'
- }
- }) app.directive('tsTplfile',
- function() {
- return {
- restrict: 'EAC',
- templateUrl: '/static/tpl.html'
- }
- });
- app.directive('tsTplscript',
- function() {
- return {
- restrict: 'EAC',
- templateUrl: 'tpl',
- replace: true
- }
- });
- //templateUrl属性值是添加的缓存名称,加速文件访问
- app.directive('tsTplcache',
- function() {
- return {
- restrict: 'EAC',
- templateUrl: 'cache'
- }
- }) < /script>/
2. 重要指令
2.1 transclude
- <script type="text/ng-template" id='tpl'>
- < div > <input type = "text"ng - model = 'text' / ><div ng - transclude > </div>
- </div >
- </script>
- <ts-tplscript>
- {{text}}
- </ts-tplscript>
- <script type="text/javascript">
- var app = angular.module('myapp', []);
- app.directive('tsTplscript',
- function() {
- return {
- restrict: 'EAC',
- templateUrl: 'tpl',
- transclude: true
- }
- });
- </script>
关于 transclude 更加详细的介绍,参见另外一篇文章
2.2 link
link 属性的值是一个函数,在该函数中可以操控 DOM 元素的对象,包括绑定元素的各类事件,定义事件触发时执行的内容等:
- link:function(scope,iEle,iAttrs)
link 函数包括 3 个主要的参数,其中,scope 参数表示指令所在的作用域,它的功能与页面中控制器注入的作用域是相同的,iEle 参数表示指令中的元素,该元素可以通过 Angular 内部封装的 jqLite 进行调用,jqLite 相当于是一个压缩版的 jQuery,包含了主要的元素操作 API,在语法上与 jQuery 类似,iAttrs 参数表示指令元素的属性集合,通过这个参数可以获取元素中的各类属性。
- <script type="text/ng-template" id='tpl'>
- < button > 单击按钮 < /button>
- /
- </script>
- <div>
- <ts-tplscript>
- </ts-tplscript>
- <div>
- {{content}}
- </div>
- </div>
- <script type="text/javascript">
- var app = angular.module('myapp', []);
- app.directive('tsTplscript',
- function() {
- return {
- restrict: 'EAC',
- templateUrl: 'tpl',
- replace: true,
- link: function(scope, iEle, iAttrs) {
- iEle.bind('click',
- function() {
- scope.$apply(function() {
- scope.content = '这是点击后的内容';
- }) iAttrs.$$element[0].disabled = true; //这里也可以替换为this.disabled=true;
- });
- }
- }
- });
- </script>
自定义 tsTplscript 指令时,在指令返回的对象中添加了 link 属性,用于绑定和执行 DOM 元素的各类事件,在属性值执行的函数中,添加 scope,iEle,iAttrs 三个参数,在指令执行的过程中,由于指令中并没有定义 scope 属性,因此,scope 参数默认就是元素外层父级 scope 属性,即控制器注入的 $scope 属性。
此外,iEle 参数就是被指令模板替换后的元素,由于在 Angular 中引入了 jqLite,因此可以直接调用 bind 方法绑定元素的各类事件,在执行事件函数的时候,调用了 scope 属性的 $apply 方法,它的功能是在执行完方法中的函数之后,重新渲染页面视图。
iAttrs 参数是指令元素的属性集合,$$element 则表示与属性对应的元素集合,该集合是一个数组。
2.3 compile
- <div ng-controller='myController'>
- <ts-a>
- <ts-b>
- {{tip}}
- </ts-b>
- </ts-a>
- </div>
- <script type="text/javascript">
- var app = angular.module('myapp', []);
- app.controller('myController',
- function($scope) {
- $scope.tip = '跟踪compile执行过程 ';
- });
- app.directive('tsA',
- function() {
- return {
- restrict: 'EAC',
- compile: function(tEle, tAttrs, trans) {
- console.log('正在编译A指令');
- //返回一个对象时,对象中包含两个名为`pre`和`post`的方法函数
- return {
- pre: function(scope, iEle, iAttrs) {
- console.log('正在执行A中的pre函数');
- },
- post: function(scope, iEle, iAttrs) {
- console.log('正在执行A中的post函数');
- }
- }
- }
- }
- });
- app.directive('tsB',
- function() {
- return {
- compile: function(tEle, tAttrs, trans) {
- console.log('正在编译B指令');
- return {
- pre: function(scope, iEle, iAttrs) {
- console.log('正在执行B中的pre函数');
- },
- post: function(scope, iEle, iAttrs) {
- console.log('正在执行B中的post函数');
- }
- }
- }
- }
- })
- </script>
控制台依次输出:
- 正在编译A指令
- 正在编译B指令
- 正在执行A中的pre函数
- 正在执行B中的pre函数
- 正在执行B中的post函数
- 正在执行A中的post函数
2.4 scope
2.4.1 当 scope 值是布尔类型
scope 属性自定义指令时,默认值就是布尔类型的,初始值为 false,在这种情况下,指令中的作用域就是指令元素所在的作用域,如果 scope 属性值为 false,表示不创建新的作用域,直接继承父级作用域,二者数据完全相同,一方有变化,另外一方面将会自动变化。
如果 scope 属性值为 true,表示子作用域是独立创建的,当它的内容发生变化时,并不会修改父作用域中的内容,不仅如此,一旦某个属性被子作用域进行了重置,那么,即使父作用域中的内容变化了,子作用域对应的内容也不会随之变化。
- <script type="text/ng-template" id='tpl'>
- < div > {
- {
- message
- }
- } < /div>
- <button ng-transclude></button >
- </script>
- <div>
- <input type="text" ng-model='message' />
- <ts-message>
- 固定
- </ts-message>
- </div>
- <script type="text/javascript">
- var app = angular.module('myapp', []);
- app.directive('tsMessage',
- function() {
- return {
- restrict: 'EAC',
- templateUrl: 'tpl',
- transclude: true,
- scope: true,
- link: function(scope, iEle, iAttrs) {
- iEle.bind('click',
- function() {
- scope.$apply(function() {
- scope.message = '这是单击按钮后的值。'
- })
- })
- }
- }
- });
- </script>
在单击按钮之前,子作用域中的值随父作用域改变,当单击按钮之后,手动重置了子作用域中的'message'遍历,但与变量绑定的父作用域的内容并没有变化,并且子作用域也不再随父作用域发生变化。
2.4.2 当 scope 值是对象
如果将 scope 属性值设置成一个 JSON 对象,那么父作用域与子作用域完全独立,不存在任何关联。
当指令中的 scope 属性值是 JSON 对象时,如果子作用域需要添加属性,必须先添加指令中的 link 函数,然后通过函数中的 scope 对象进行添加,如果在子作用域中,要绑定或调用父父作用域中的属性和方法,则需要在 scope 属性对应的 JSON 对象值中添加绑定策略。
严格来说,在 JSON 对象中添加的有 3 种绑定策略:@ = &
1、@
@绑定与将 scope 值设为 true,有许多相同的地方,唯一不同之处在于,@绑定在子作用域充值属性之后,再返回修改父作用域对应属性内容时,子作用域对应的属性,同样还是会随之发生变化,而使用 scope:true,则不会发生这一步。
2、=
= 绑定的功能是创建一个父与子作用域可以同时共享的属性,即当父作用域修改了该属性,子作用域也随之变化,反之亦然,两个作用域间完全共享和同步。
3、&
& 绑定的功能是可以在独立的子作用域中直接调用父作用域的方法,在调用时可以向函数传递参数,这种功能的好处在于,避免重复编写功能相同的代码,只需要进行简单的绑定设置,就可以使指令执行后,轻松调用控制器中的方法。
- <script type="text/ng-template" id='tpl'>
- < div > <span > 姓名: {
- {
- textName
- }
- } < /span>
- <span>年龄:{{textAge}}</span > </div>
- <button ng-transclude></button >
- </script>
- <div ng-controller="myController">
- 姓名:
- <input type="text" ng-model='text_name' />
- <br>
- 年龄:
- <input type="text" ng-model='text_age' />
- <br>
- <div>
- {{tip}}
- </div>
- <ts-json a-attr="{{text_name}}" b-attr="text_age" reset="reSet()">
- 重置
- </ts-json>
- </div>
- <script type="text/javascript">
- var app = angular.module('myapp', []);
- app.controller('myController',
- function($scope) {
- $scope.reSet = function() {
- $scope.tip = '姓名与年龄重置成功!';
- }
- });
- app.directive('tsJson',
- function() {
- return {
- restrict: 'EAC',
- templateUrl: 'tpl',
- transclude: true,
- scope: {
- textName: '@aAttr',
- textAge: '=bAttr',
- reSet: '&reset'
- },
- link: function(scope, iEle, iAttrs) {
- iEle.bind('click',
- function() {
- scope.$apply(function() {
- scope.reSet();
- scope.textName = '张三';
- scope.textAge = '20';
- })
- })
- }
- }
- });
- </script>
绑定的过程:
先在指令元素中创建 a-attr 或 b-attr 属性,由于 HTML 不区分大小写,因此使用 - 隔开。
需要注意的是:由于在指令中绑定策略不同,在指令元素中,属性绑定属性值也会有些变化,使用 @绑定的属性,绑定属性值的方式为双大括号 {{}},而使用 = 绑定的属性,绑定属性值的方式为等于号 =,不需要双大括号.
2.5 require 和 controller
当一个子元素需要与一个父元素指令通信时,就需要添加并使用这两个属性值。
- <div>
- <ts-parent>
- <div>
- {{ptip}}
- </div>
- <ts-child>
- <div>
- {{ctip}}
- </div>
- </ts-child>
- <button ng-click='click()'>
- 换位
- </button>
- </ts-parent>
- </div>
- <script type="text/javascript">
- var app = angular.module('myapp', []);
- app.directive('tsParent',
- function() {
- return {
- restrict: 'EAC',
- controller: function($scope, $compile, $http) {
- this.addChild = function(c) {
- $scope.ptip = '今天天气不错!';
- $scope.click = function() {
- $scope.tmp = $scope.ptip;
- $scope.ptip = c.ctip;
- c.ctip = $scope.tmp;
- }
- }
- }
- }
- });
- app.directive('tsChild',
- function() {
- return {
- restrict: 'EAC',
- require: '^?tsParent',
- link: function(scope, iEle, iAttrs, ctrl) {
- scope.ctip = '气温正好18摄氏度';
- ctrl.addChild(scope);
- }
- }
- })
- </script>
总结
来源: http://www.jb51.net/article/114558.htm