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 相关文章推荐
网上应用的一个不错common.js脚本
Aug 08 Javascript
JS数字抽奖游戏实现方法
May 04 Javascript
浅谈使用MVC模式进行JavaScript程序开发
Nov 10 Javascript
基于JavaScript实现回到页面顶部动画代码
May 24 Javascript
javascript动画之模拟拖拽效果篇
Sep 26 Javascript
js原生实现FastClick事件的实例
Nov 20 Javascript
thinkjs之页面跳转同步异步操作
Feb 05 Javascript
JavaScript你不知道的一些数组方法
Aug 18 Javascript
js 两个日期比较相差多少天的实例
Oct 19 Javascript
vue自定义键盘信息、监听数据变化的方法示例【基于vm.$watch】
Mar 16 Javascript
vue响应式系统之observe、watcher、dep的源码解析
Apr 09 Javascript
JavaScript实现栈结构详细过程
Dec 06 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
快速配置PHPMyAdmin方法
2008/06/05 PHP
php递归创建和删除文件夹的代码小结
2012/04/13 PHP
解析PHP中的正则表达式以及模式匹配
2013/06/19 PHP
对于PHP 5.4 你必须要知道的
2013/08/07 PHP
PHP自定义图片缩放函数实现等比例不失真缩放的方法
2016/08/19 PHP
php微信公众号js-sdk开发应用
2016/11/28 PHP
定时器(setTimeout/setInterval)调用带参函数失效解决方法
2013/03/26 Javascript
给ListBox添加双击事件示例代码
2013/12/02 Javascript
$.extend 的一个小问题
2015/06/18 Javascript
10道典型的JavaScript面试题
2017/03/22 Javascript
JavaScript初学者必看“new”
2017/06/12 Javascript
json数据传到前台并解析展示成列表的方法
2018/08/06 Javascript
使用VUE+iView+.Net Core上传图片的方法示例
2019/01/04 Javascript
JavaScript常用工具方法封装
2019/02/12 Javascript
微信小程序实现元素渐入渐出动画效果封装方法
2019/05/18 Javascript
Vue实现日历小插件
2019/06/26 Javascript
javascript的hashCode函数实现代码小结
2020/08/11 Javascript
[01:45]2014DOTA2 TI预选赛预选赛 战前探营!
2014/05/21 DOTA
Python程序语言快速上手教程
2012/07/18 Python
Python编写百度贴吧的简单爬虫
2015/04/02 Python
Python编程之string相关操作实例详解
2017/07/22 Python
django在接受post请求时显示403forbidden实例解析
2018/01/25 Python
pandas 将list切分后存入DataFrame中的实例
2018/07/03 Python
python: 自动安装缺失库文件的方法
2018/10/22 Python
python 类的继承 实例方法.静态方法.类方法的代码解析
2019/08/23 Python
零基础学Python之前需要学c语言吗
2020/07/21 Python
python 实用工具状态机transitions
2020/11/21 Python
米兰必去买手店排行榜首位:Antonioli
2016/09/11 全球购物
新学期决心书
2014/03/11 职场文书
副职竞争上岗演讲稿
2014/05/12 职场文书
霸气队列口号
2014/06/18 职场文书
离婚协议书标准格式
2014/10/04 职场文书
教师个人总结范文
2015/02/11 职场文书
合作合同协议书
2016/03/21 职场文书
使用PDF.js渲染canvas实现预览pdf的效果示例
2021/04/17 Javascript
实现AJAX异步调用和局部刷新的基本步骤
2022/03/17 Javascript