AngularJS自定义指令

AngularJS为我们提供了自定义指令的功能,通过此功能,我们可以自定义一些标签,为我们的开发提供帮助,其实一些大型公司都存在自定义标签,为快速开发提供了基础。

定义自定义指令一般有两种方式

1.第一种,在module()的第三个参数中定义

代码如下:
index01.html

<html ng-app="myApp">
    <head>
        <meta charset="UTF-8">
        <title>title>
        <script type="text/javascript" src="../js/angular-1.3.14.min.js" >script>
        <script type="text/javascript" src="index01.js" >script>
    head>
    <body ng-controller="myController">
        
        <div my-directive>div>

        

        <my-directive>my-directive>

        

        <div class="myDirective">div>

        

        

    body>
html>
index01.js
angular.module("myApp",[],['$compileProvider',function($compileProvider){
    $compileProvider.directive("myDirective",function(){
        return {
            "restrict":"ECMA",/*E-element,C-class,M 注释,A-attribute*/
            "template":"

hello,directive

"
, 'replace':true/*将html页面引用这个指令的标签替换掉*/ } }); }]) .controller("myController",function($scope){});

2.第二种定义自定义指令方式-基于directive的方式

index02.html

<html ng-app="myApp">
    <head>
        <meta charset="UTF-8">
        <title>title>
        <script type="text/javascript" src="../js/angular-1.3.14.min.js" >script>
        <script type="text/javascript" src="index02.js" >script>
    head>
    <body>
        
        <div my-directive>div>

        

        <my-directive>my-directive>

        

        <div class="myDirective">div>

        

        

    body>
html>
index02.js

angular.module("myApp",[])
.directive("myDirective",function(){
    return {
        "restrict":'ECMA',
        "template":"

hello,directive1.

"
, "replace":true//用replace时,必须要有一个节点包裹才能替换 /* * templateUrl:导入模板的路径 * * */ } });

测试templateUrl的用法

index03.html



<html ng-app="myApp">
    <head>
        <meta charset="UTF-8">
        <title>title>
        <script type="text/javascript" src="../js/angular-1.3.14.min.js" >script>
        <script type="text/javascript" src="index03.js" >script>
    head>
    <body>
        
        <div my-directive>div>

        

        <my-directive>my-directive>

        

        <div class="myDirective">div>

        

        
    body>
html>
index003.html

this is a templateUrl test.

index03.js

angular.module("myApp",[])
.directive("myDirective",function(){
    return {
        "restrict":"ECMA",
        "templateUrl":"index003.html",
        "replace":true
    }

});

transclude属性-是否保留原标签内的内容

index.html


<html ng-app="myApp">
    <head>
        <meta charset="UTF-8">
        <title>title>
        <script type="text/javascript" src="../js/angular-1.3.14.min.js" >script>
        <script type="text/javascript" src="index04.js" >script>
    head>
    <body>
        <div my-directive1>this is my div.div>
    body>
html>

i

ndex.js

angular.module("myApp",[])
.directive("myDirective1",function(){
    return {
        "restrict":"ECMA",
        "template":"

this is directive1.

"
, "replace":true, "transclude":true//保存原标签内的值 } });

priority属性-指令在模块中执行的优先级别

terminal属性-是否以当前指令的权重为结束界限

index.html


<html ng-app="myApp">
    <head>
        <meta charset="UTF-8">
        <title>title>
        <script type="text/javascript" src="../js/angular-1.3.14.min.js" >script>
        <script type="text/javascript" src="index05.js" >script>
    head>
    <body>
        <div my-directive1 my-directive2>div>
    body>
html>
index.js

angular.module("myApp",[])
.directive("myDirective1",function(){
    return {
        "restrict":"ECMA",
        "template":"

this is directive1.

"
, "replace":true, "priority":0 } }) .directive("myDirective2",function(){ return { "restrict":"ECMA", "template":"

this is directive2.

"
, "replace":true, "priority":10, "terminal":true } });

compile属性和link属性

要使用compile和link,首先了解AngularJS指令的编译过程
1.第一阶段:
标准浏览器API的转化—-就是将html转化为dom。
2.第二阶段:
AngularJS的compile—-搜索匹配directive,按照priority排序,并执行directive上的compile方法
3.第三阶段:
AngularJS link—–执行directive上的link方法,进行scope绑定及事件绑定。

compile

  • compile方法的定义为:compile:function(tElement,tAttris,transclude).
  • compile函数用来对模板自身进行转换仅仅在编译阶段运行一次
  • compile中直接返回的函数是postlink,表示link参数需要执行的函数,也可以返回一个对象里面包含prelink和postlink。
  • 当定义compile参数时,将无视link参数,因为compile里返回的就是该指令需要执行的link函数。
  • link方法的定义为:link:function(scope,iElement,iAttris,controller).
  • link函数代表的是compile函数返回的postlink。
  • prelink表示在编译阶段后,指令连接到子元素之前运行,
  • postlink表示在所有的子元素都连接之后运行
  • link函数负责在模型和视图之间进行动态关联,对于每个指令的每个实例,link函数都会执行一次。

compile和link的使用动机

compile
想在dom渲染前对它进行变形(如添加节点等),并且不需要scope参数,想在所有相同directive里共享某些方法,这时应该定义在compile里,性能会比较好,返回值就是link函数,这时就是共同使用的时候。

对特定的元素注册事件,需要用到scope参数来实现dom元素的一些行为

代码演示:
index.html


<html ng-app="myApp">
    <head>
        <meta charset="UTF-8">
        <title>title>
        <script type="text/javascript" src="../js/angular-1.3.14.min.js" >script>
        <script type="text/javascript" src="index06.js" >script>
    head>
    <body>
        <div my-directive>div>
    body>
html>
index.js

angular.module("myApp",[])
.directive("myDirective",function(){
    return {
        "restrict":"ECMA",
        "template":"

this is testController.

"
, "controller":function($scope){ console.log("controller...");//进行值的传递 }, "compile":function(tElement,tAttris,transclude){ /* * compile:返回值就是link函数,在指令编译过程的第三阶段运行 * * */ return { //编译阶段之后,指令连接子元素之前 "pre":function preList(){ console.log("pre..."); }, //在编译阶段之后,指令连接子元素之后 "post":function postList(){ console.log("post"); } } }, } });

controller和controllerAs属性:

controller

为自定义的指令添加一个控制器,使得多个指令之间可以通信

controllerAs

为controller定义一个别名
代码演示:
index.html


<html ng-app="myApp">
    <head>
        <meta charset="UTF-8">
        <title>title>
        <script type="text/javascript" src="../js/angular-1.3.14.min.js" >script>
        <script type="text/javascript" src="index08.js" >script>
    head>
    <body>
        <div my-directive>div>
    body>
html>
index.js


angular.module("myApp",[])
.directive("myDirective",function(){
    return {
        "restrict":"ECMA",
        "template":"

this is controller test.

{{name}}
"
, "controller":function($scope){ $scope.name='this is controller.'; }, "controllerAs":"myControl", "link":function(scope,iElement,iAttris,myControl){ console.log(scope.name); iElement.on("click",function(){ alert("hello,angularjs.") }); } } });
运行结果如下:

AngularJS自定义指令_第1张图片

require属性—可以将其它指令传递给自己

  • directiveName 通过驼峰法的命名制定控制器应该带有那个指令,默认会从同一个元素上的指令
  • ^directiveName 从父级查找指令
  • ?directiveName 表示指令是可选的,如果找不到,也不会抛出异常
代码演示如下:
index.html



<html ng-app="myApp">
    <head>
        <meta charset="UTF-8">
        <title>title>
        <script type="text/javascript" src="../js/angular-1.3.14.min.js" >script>
        <script type="text/javascript" src="index07.js" >script>
    head>
    <body>
        <div my-directive>div>
    body>
html>
index.js


angular.module("myApp",[])
.directive("myDirective",function(){
    return {
        "restrict":"ECMA",
        "template":"
  • {{book.name}}
"
, "controller":function($scope){ $scope.books=[{ "name":"嘻游记", "id":12 },{ "name":"东游记", "id":13 }]; this.addBook=function(){ $scope.$apply(function(){ $scope.books.push({ "name":"哈游记", "id":11 }); }); } }, "controllerAs":"booklist", "replace":true } }) .directive("bookAdd",function(){ return { "restrict":"ECMA", "require":"^myDirective", "template":"", "replace":true, "link":function(scope,iElement,iAttris,booklist){ iElement.on("click",booklist.addBook); } } });

scope属性—新定义一个作用域,而不是继承的父级作用域

var myApp = angular.module("myApp",[]);
myApp
.directive("myDirective",function() {
    return {
        "restrict" : "AEMC",
        "template" : "
  • {{book.name}}
"
, "controller" : function($scope) { console.info($scope) }, /** * scope默认为false,表示使用同一个作用域, * 但是当我们设置为true时,此时,就是controller * 的作用域就是一个独立的作用域 */ "scope" : true, "replace" : true } }) .controller("myCon",["$scope",function($scope) { console.info($scope) }]);
如果默认或者scope设置为false,则所有的controller默认一个作用域,但是当我们设置scope为真的时候,该controller则是一个独立的作用域。
  • false 继承父级元素的作用域
  • true 创建一个新的作用域,但是可以向上得到父级作用域
  • object 独立的scope,父级无法得到,作用域链是断的
  • object的参数:
  • &:作用域把父级作用域的属性包装成了一个函数,从而以函数的方式读写父作用域的属性。
  • =:作用域的属性与父作用域进行了双向绑定,任何一方的修改均影响到对方。
  • @:只能读取父作用域里的值单向绑定。
代码演示如下:
index.html



<html ng-app="myApp">
    <head>
        <meta charset="UTF-8">
        <title>title>
        <script type="text/javascript" src="../js/angular-1.3.14.min.js" >script>
        <script type="text/javascript" src="index09.js" >script>
    head>
    <body ng-controller="myCon">
        {{books}}==={{msg}}
        <div my-directive bb="books" parent-books="books" scope-books="{{msg}}">div>
    body>
html>
index.js

var myApp = angular.module("myApp",[]);
myApp
.directive("myDirective",function() {
    return {
        "restrict" : "AEMC",
        "template" : "
  • {{book.name}}====={{msg}}
"
, "controller" : function($scope) { // console.info($scope.$parent.books) // $scope.books = $scope.$parent.books; $scope.books = $scope.aaa(); // $scope.books = $scope.bbb; // $scope.bbb.push({ // "name" : "PHP", // "price" : 30 // }); console.info($scope.ccc) $scope.msg = $scope.ccc; $scope.msg = "哈哈"; }, /** * scope默认为false,表示使用同一个作用域, * 但是当我们设置为true时,此时,就是controller * 的作用域就是一个独立的作用域 */ // "scope" : true, /** * 当scope是一个对象的时候,作用域也是一个 * 独立的作用域,但是无法共享父级作用域 */ "scope" : { //将父元素中的books封装成a函数 aaa: "&bb", //数据与父元素双向绑定 // bbb: "=parentBooks", //注意,只能传递字符串等基本数据类型, //子类修改值,父类不会受到影响 ccc: "@scopeBooks" }, "replace" : true } }) .controller("myCon",["$scope","$rootScope",function($scope,rs) { $scope.books = [ { "name" : "javascript", "price" : 15.6 },{ "name" : "java", "price" : 20 } ]; $scope.msg = "this is a test."; // console.info($scope); // console.log(rs) }]);

你可能感兴趣的:(angularjs)