欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Angular之指令Directive用法详解

程序员文章站 2022-09-02 11:10:36
项目筹备近期开启angular学习,指令比较难理解所以记录备案,推荐视频大漠穷秋 angular实战 由于篇幅过长,列举大纲如下: 一、指令directive概述...

项目筹备近期开启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'

 }

}); 

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