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 相关文章推荐
js removeChild 障眼法 可能出现的错误
Oct 06 Javascript
ExtJs 3.1 XmlTreeLoader Example Error
Feb 09 Javascript
Jquery cookie操作代码
Mar 14 Javascript
JS图片预加载 JS实现图片预加载应用
Dec 03 Javascript
优化Jquery,提升网页加载速度
Nov 14 Javascript
JQuery Mobile实现导航栏和页脚
Mar 09 Javascript
解决vue2 在mounted函数无法获取prop中的变量问题
Nov 15 Javascript
layui-laydate时间日历控件使用方法详解
Nov 15 Javascript
vue实现百度下拉列表交互操作示例
Mar 12 Javascript
vue路由教程之静态路由
Sep 03 Javascript
vue addRoutes路由动态加载操作
Aug 04 Javascript
通过vue.extend实现消息提示弹框的方法记录
Jan 07 Vue.js
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 邮件发送问题解决
2014/03/22 PHP
PHP中魔术变量__METHOD__与__FUNCTION__的区别
2014/09/29 PHP
php中get_defined_constants函数用法实例分析
2015/05/12 PHP
微信公众平台开发之配置与请求
2015/08/26 PHP
PHP使用strrev翻转中文乱码问题的解决方法
2017/01/13 PHP
PHP命名空间namespace及use的简单用法分析
2018/08/03 PHP
YII框架常用技巧总结
2019/04/27 PHP
不用MOUSEMOVE也能滑动啊
2007/05/23 Javascript
JS OffsetParent属性深入解析
2014/01/13 Javascript
JS和函数式语言的三特性
2014/03/05 Javascript
javascript模拟订火车票和退票示例
2014/04/24 Javascript
node.js中的fs.utimesSync方法使用说明
2014/12/15 Javascript
基于Vue的移动端图片裁剪组件功能
2017/11/28 Javascript
Vue.js 实现数据展示全部和收起功能
2018/09/05 Javascript
vue基于element的区间选择组件
2018/09/07 Javascript
详解vue+axios给开发环境和生产环境配置不同的接口地址
2019/08/16 Javascript
Pycharm学习教程(5) Python快捷键相关设置
2017/05/03 Python
Python 判断 有向图 是否有环的实例讲解
2018/02/01 Python
python自动登录12306并自动点击验证码完成登录的实现源代码
2018/04/25 Python
Python为何不能用可变对象作为默认参数的值
2019/07/01 Python
python实现树的深度优先遍历与广度优先遍历详解
2019/10/26 Python
Python中join()函数多种操作代码实例
2020/01/13 Python
详解用Python进行时间序列预测的7种方法
2020/03/13 Python
Python实现常见的几种加密算法(MD5,SHA-1,HMAC,DES/AES,RSA和ECC)
2020/05/09 Python
Selenium 安装和简单使用的实现
2020/12/04 Python
详解通过变换矩阵实现canvas的缩放功能
2019/01/14 HTML / CSS
法国娇韵诗官方旗舰店:Clarins是来自法国的天然护肤品牌
2018/06/30 全球购物
加拿大时装零售商:Influence U
2018/12/22 全球购物
Pottery Barn阿联酋:购买家具、家居装饰及更多
2019/12/08 全球购物
工商管理实习自我鉴定
2013/09/28 职场文书
公司晚会策划方案
2014/05/17 职场文书
十佳青年事迹材料
2014/08/21 职场文书
作风大整顿心得体会
2014/09/10 职场文书
2015上半年个人工作总结
2015/07/27 职场文书
技术入股合作协议书
2016/03/21 职场文书
Win11绿屏怎么办?Win11绿屏死机的解决方法
2021/11/21 数码科技