AngularJS自定义指令

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

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

1.第一种,在module()的第三个参数中定义
代码如下:
index01.html
<!DOCTYPE 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">
        <!--
            作者:1404578601@qq.com
            时间:2016-10-24
            描述:作为属性
        -->
        <div my-directive></div>

        <!--
            作者:1404578601@qq.com
            时间:2016-10-24
            描述:作为标签
        -->

        <my-directive></my-directive>

        <!--
            作者:1404578601@qq.com
            时间:2016-10-24
            描述:作为类名
        -->

        <div class="myDirective"></div>

        <!--
            作者:1404578601@qq.com
            时间:2016-10-24
            描述:作为注释
        -->

        <!--
            directive:myDirective
        -->

    </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":"<h1>hello,directive</h1>",
            'replace':true/*将html页面引用这个指令的标签替换掉*/
        }
    });
}])
.controller("myController",function($scope){});
2.第二种定义自定义指令方式-基于directive的方式
index02.html
<!DOCTYPE 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>
        <!--
            作者:1404578601@qq.com
            时间:2016-10-24
            描述:作为属性
        -->
        <div my-directive></div>

        <!--
            作者:1404578601@qq.com
            时间:2016-10-24
            描述:作为标签
        -->

        <my-directive></my-directive>

        <!--
            作者:1404578601@qq.com
            时间:2016-10-24
            描述:作为类名
        -->

        <div class="myDirective"></div>

        <!--
            作者:1404578601@qq.com
            时间:2016-10-24
            描述:作为注释
        -->

        <!--
            directive:myDirective
        -->

    </body>
</html>
index02.js

angular.module("myApp",[])
.directive("myDirective",function(){
    return {
        "restrict":'ECMA',
        "template":"<h1>hello,directive1.</h1>",
        "replace":true//用replace时,必须要有一个节点包裹才能替换

        /*

         * templateUrl:导入模板的路径
         * 
         * */
    }
});
测试templateUrl的用法
index03.html


<!DOCTYPE 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>
        <!--
            作者:1404578601@qq.com
            时间:2016-10-24
            描述:作为属性
        -->
        <div my-directive></div>

        <!--
            作者:1404578601@qq.com
            时间:2016-10-24
            描述:作为标签
        -->

        <my-directive></my-directive>

        <!--
            作者:1404578601@qq.com
            时间:2016-10-24
            描述:作为类名
        -->

        <div class="myDirective"></div>

        <!--
            作者:1404578601@qq.com
            时间:2016-10-24
            描述:作为注释
        -->

        <!--
            directive:myDirective
        -->
    </body>
</html>
index003.html

<h1>this is a templateUrl test.</h1>
index03.js

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

});
transclude属性-是否保留原标签内的内容
index.html

<!DOCTYPE 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":"<h2>this is directive1.<p ng-transclude></p></h2>",
        "replace":true,
        "transclude":true//保存原标签内的值
    }
});
priority属性-指令在模块中执行的优先级别
terminal属性-是否以当前指令的权重为结束界限
index.html

<!DOCTYPE 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":"<h3>this is directive1.</h3>",
        "replace":true,
        "priority":0
    }
})
.directive("myDirective2",function(){
    return {
        "restrict":"ECMA",
        "template":"<h3>this is directive2.</h3>",
        "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

<!DOCTYPE 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":"<h1>this is testController.</h1>",
        "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

<!DOCTYPE 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":"<div><h3>this is controller test.</h3>{{name}}</div>",
        "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.")
            });
        }
    }
});
运行结果如下:

这里写图片描述

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


<!DOCTYPE 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":"<div><ul><li ng-repeat='book in books'>{{book.name}}</li></ul><book-add></book-add></div>",
        "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":"<button>添加课本</button>",
        "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" : "<div><ul><li ng-repeat='book in books'>{{book.name}}</li></ul></div>",
        "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


<!DOCTYPE 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" : "<div><ul><li ng-repeat='book in books'>{{book.name}}====={{msg}}</li></ul></div>",
        "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)
}]);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值