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 相关文章推荐
nicejforms——美化表单不用愁
Feb 20 Javascript
javascript Array.sort() 跨浏览器下需要考虑的问题
Dec 07 Javascript
JQuery表格内容过滤的实现方法
Jul 05 Javascript
tuzhu_req.js 实现仿百度图片首页效果
Aug 11 Javascript
JS+CSS实现的日本门户网站经典选项卡导航效果
Sep 27 Javascript
JavaScript 2048 游戏实例代码(简单易懂)
Mar 25 Javascript
详解jQuery中ajax.load()方法
Jan 25 Javascript
Three.js利用性能插件stats实现性能监听的方法
Sep 25 Javascript
深入掌握 react的 setState的工作机制
Sep 27 Javascript
浅谈Vue.js路由管理器 Vue Router
Aug 16 Javascript
webuploader分片上传的实现代码(前后端分离)
Sep 10 Javascript
JavaScript实现点击自制菜单效果
Feb 02 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
先进的自动咖啡技术,真的可以取代咖啡师吗?
2021/03/06 冲泡冲煮
Php Cookie的一个使用注意点
2008/11/08 PHP
PHP使用redis实现统计缓存mysql压力的方法
2015/11/14 PHP
Linux下源码包安装Swoole及基本使用操作图文详解
2019/04/02 PHP
基于jQuery创建鼠标悬停效果的方法
2015/03/07 Javascript
javascript模块化简单解析
2016/04/07 Javascript
jQuery实现鼠标跟随提示层效果代码(可显示文本,Div,Table,Html等)
2016/04/18 Javascript
想学习javascript JS和jQuery哪个重要 先学哪个
2016/12/11 Javascript
js图片放大镜效果实现方法详解
2020/10/28 Javascript
jQuery响应滚动条事件功能示例
2017/10/14 jQuery
vue-router2.0 组件之间传参及获取动态参数的方法
2017/11/10 Javascript
代码实例ajax实现点击加载更多数据图片
2018/10/12 Javascript
layui表单验证select下拉框实现验证的方法
2019/09/05 Javascript
[03:49]DOTA2英雄基础教程 光之守卫
2014/01/14 DOTA
[39:53]完美世界DOTA2联赛PWL S2 LBZS vs Forest 第一场 11.19
2020/11/19 DOTA
Python 时间操作例子和时间格式化参数小结
2014/04/24 Python
Python加pyGame实现的简单拼图游戏实例
2015/05/15 Python
Python中Class类用法实例分析
2015/11/12 Python
用yum安装MySQLdb模块的步骤方法
2016/12/15 Python
Python实现找出数组中第2大数字的方法示例
2018/03/26 Python
python自动登录12306并自动点击验证码完成登录的实现源代码
2018/04/25 Python
对pandas数据判断是否为NaN值的方法详解
2018/11/06 Python
Python3调用百度AI识别图片中的文字功能示例【测试可用】
2019/03/13 Python
深入浅析python的第三方库pandas
2020/02/13 Python
python实现ssh及sftp功能(实例代码)
2020/03/16 Python
django 解决自定义序列化返回处理数据为null的问题
2020/05/20 Python
Python爬虫爬取有道实现翻译功能
2020/11/27 Python
复古风格的女装和装饰品:ModCloth
2017/12/29 全球购物
美国机场停车位预订:About Airport Parking
2018/03/26 全球购物
俄罗斯大型在线书店:Читай-город
2019/10/10 全球购物
C语言面试题
2013/05/19 面试题
综合实践活动总结
2014/05/05 职场文书
2015年实习单位评语
2015/03/25 职场文书
民事撤诉申请书范本
2015/05/18 职场文书
建国大业观后感600字
2015/06/01 职场文书
关于拾金不昧的感谢信(五篇)
2019/10/18 职场文书