Angular之指令Directive用法详解


Posted in Javascript onMarch 01, 2017

项目筹备近期开启Angular学习,指令比较难理解所以记录备案,推荐视频大漠穷秋 Angular实战 由于篇幅过长,列举大纲如下:

Angular之指令Directive用法详解

一、指令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结构如下

Angular之指令Directive用法详解

replace:false 或没有replace属性时浏览器DOM结构如下

Angular之指令Directive用法详解

三、指令之嵌套变换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运行原理

Angular之指令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作用域绑定策略

Angular之指令Directive用法详解 

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'

 }

});

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
如何在Mozilla Gecko 用Javascript加载XSL
Jan 09 Javascript
可以支持多中格式的JS键盘
May 02 Javascript
formvalidator验证插件中有关ajax验证问题
Jan 04 Javascript
js如何实现设计模式中的模板方法
Jul 23 Javascript
理解javascript中的with关键字
Feb 15 Javascript
jQuery遍历DOM元素与节点方法详解
Apr 14 Javascript
javascript运算符——逻辑运算符全面解析
Jun 27 Javascript
微信小程序-小说阅读小程序实例(demo)
Jan 12 Javascript
node.js基于fs模块对系统文件及目录进行读写操作的方法详解
Nov 10 Javascript
动态加载、移除js/css文件的示例代码
Mar 20 Javascript
bootstrap下拉分页样式 带跳转页码
Dec 29 Javascript
初学vue出现空格警告的原因及其解决方案
Oct 31 Javascript
js for循环倒序输出数组元素的实例
Mar 01 #Javascript
JSON与JS对象的区别与对比
Mar 01 #Javascript
JavaScript下拉菜单功能实例代码
Mar 01 #Javascript
Angular2 路由问题修复详解
Mar 01 #Javascript
浅谈js for循环输出i为同一值的问题
Mar 01 #Javascript
jQuery EasyUI Draggable拖动组件
Mar 01 #Javascript
Angular.js之作用域scope'@','=','&amp;'实例详解
Feb 28 #Javascript
You might like
Php注入点构造代码
2008/06/14 PHP
PHP数据库万能引擎类adodb配置使用以及实例集锦
2014/06/12 PHP
Yii框架组件和事件行为管理详解
2016/05/20 PHP
Laravel手动分页实现方法详解
2016/10/09 PHP
详解PHP归并排序的实现
2016/10/18 PHP
php获取POST数据的三种方法实例详解
2016/12/20 PHP
laravel框架模板之公共模板、继承、包含实现方法分析
2019/08/30 PHP
PHP 面向对象程序设计之类属性与类常量实现方法分析
2020/04/13 PHP
使用onbeforeunload属性后的副作用
2007/03/08 Javascript
jQuery 浮动广告实现代码
2008/12/25 Javascript
开发中可能会用到的jQuery小技巧
2014/03/07 Javascript
JavaScript中的document.referrer在各种浏览器测试结果
2014/07/18 Javascript
jquery实现公告翻滚效果
2015/02/27 Javascript
JavaScript里实用的原生API汇总
2015/05/14 Javascript
JS图片放大效果简单实现代码
2016/09/08 Javascript
JavaScript插件Tab选项卡效果
2017/11/14 Javascript
vue实现导航栏效果(选中状态刷新不消失)
2017/12/13 Javascript
解析Angular 2+ 样式绑定方式
2018/01/15 Javascript
JS实现全屏预览F11功能的示例代码
2018/07/23 Javascript
vue如何进行动画的封装
2018/09/26 Javascript
iView-admin 动态路由问题的解决方法
2018/10/03 Javascript
js实现图片3D轮播效果
2019/09/21 Javascript
Python中让MySQL查询结果返回字典类型的方法
2014/08/22 Python
Python常用模块用法分析
2014/09/08 Python
Python获取Windows或Linux主机名称通用函数分享
2014/11/22 Python
使用python和pygame绘制繁花曲线的方法
2018/02/24 Python
pytorch模型预测结果与ndarray互转方式
2020/01/15 Python
基于pandas向csv添加新的行和列
2020/05/25 Python
浅析Python 责任链设计模式
2020/09/11 Python
美国家居装饰店:Z Gallerie
2020/12/28 全球购物
编程实现去掉XML的重复结点
2014/05/28 面试题
JAVA程序设计笔试题面试题一套
2015/07/28 面试题
中层干部竞争上岗演讲稿
2014/01/13 职场文书
中学劳技课教师的自我评价
2014/02/05 职场文书
物业总经理岗位职责
2014/02/28 职场文书
观看《杨善洲》宣传教育片心得体会
2016/01/23 职场文书