zoukankan      html  css  js  c++  java
  • 如何编写Angular指令

    [20140917]Angular:如何编写一个指令

    Angular是什么?

    AngularJS是一个用JavaScript编写的客户端MVC框架,它运行于Web浏览器,能够极大的帮助我们(开发者)编写模块化,单页面,Ajax风格的Web Applications。

    PS:AngularJS适合开发CRUD的SPA

    Angular Directive是什么?

    Angular Directive是构建在DOM元素(属性、标签名、注释和CSS类)上的标记,告诉AngularJS的HTML编译器($compile) 附加指定的行为到元素或者甚至变换这个元素和它的子集。

    PS:通过扩展HTML标签的方式提供可复用的web组件

    PS2:指令的作用:提供语义化标签

    完整的Directive参数

    var directiveModule=angular.module('Newkit.negHotkeys');
    directiveModule.directive('negHotkeys',function(injectables){
        var directiveDefineObject={
            restrict:(string), 
            priority:(number),
            template:(string),
            templateUrl:(string),
            replace:(bool),
            transclude:(bool),
            scope:(bool or object),
            controller:(function),
            require:(string),
            link:(function)
            compile:(function)
        };
        return directiveDefineObject;
    });
    
    参数说明
    • restrict:(string)指令的使用方式,可选值:元素[E]、属性[A]、样式类[C]、注释[M],并且可以采用组合的方式使用,示例:'AE'
    • priority:(number)优先级,描述了多个指令时,指令的执行顺序。数字越大,优先级越高,默认值0。
    • template:(string)文本模板
    • templateUrl:(string)模板文件地址,如果设置了该属性,那么将会忽略template的配置。
    • replace:(bool)指示是否替换元素,如果设置为true,则替换,否则(设置为false或不设置)追加到元素内部
    • transclude:(bool)是否将指令的子节点移动到一个新模板内部,如果在模板中指定了ng-transclude,那么会将元素原本的内容移动到新的模板内部,具体看示例二
    • scope:(bool or object)设置作用域,如果设置为false[默认值],则使用现有的作用域;如果设置为true,则创建一个新的作用域。设置为object时,设定作用域绑定策略
    • controller:创建一个控制器,它会暴露一个API,实现在多个指令之间进行通信
    • require:设置依赖的指令。不设置,则无依赖,示例:'?^testDirective',其中,?表示该指令可选,^表示需要遍历DOM树查找指令
    • link:链接函数,function(scope,iElement,iAttrs){},其中的i表示实例,所以在link中接收的是实例元素和实例元素属性
    • compile:编译函数,function(tElement,tAttrs,transclude){},其中t表示模板,所以在compile中使用的是模板元素。在编译过程中,可以返回preLink(链接前),postLink(链接后)函数,compile函数只会调用一次,而link函数的调用次数等于things中的元素个数,所以多余共同的东西,那么最好放在compile函数中实现(出于效率考虑) 注:设置了compile属性之后,指令将忽略link属性,同时compile函数的返回值将作为link函数使用

    Angular Directive 示例

    示例一(简单指令)

    /*demo1指令定义*/
    angular.module('app').directive('demo1',function(){
        return {
            restrict:'AE',/*标签或者属性*/
            template:'<div>Hello</div>',
            replace:true
        }
    });
    
    /*使用*/
    <html ng-app="app">
        <head>...</head>
        <body>  
            <demo1></demo1>
            <div data-demo1></div>
        </body>
    </html>
    
    /*结果(指令将满足条件的元素替换为了新的内容)*/
    <body>
        <div>Hello World!</div>
        <div demo1="">Hello World!</div>
    </body>
    
    操作步骤分析
    1. 定义一个模块app,并创建了一个指令demo1。
    2. 设定该指令可采用元素的标签和属性申明,并设置了一个文本模板,同时设置了replace=true。
    3. 在html中,采用标签如<demo1></demo1>和属性<div demo1></div>来实现调用

    示例二(变换)

    /*demo2指令定义*/
    angular.module('app.directive.demo2',[]).directive('demo2',function(){
        return {
            restrict:'E',
            template:'<div>This is Demo2<div ng-transclude></div></div>',
            transclude:true
        }
    });
    
    /*使用*/
    <demo2>
        <span>原始的内容,</span><br/>
        <span>还会在这里。</span>
    </demo2>
    <demo2></demo2>
    
    /*页面生成的HTML*/
    <demo2>
        <div>This is Demo2
            <div ng-transclude="">
                <span class="ng-scope">原始的内容,</span><br class="ng-scope">
                <span class="ng-scope">还会在这里。</span>
            </div>
        </div>
    </demo2>
    <demo2>
        <div>This is Demo2
            <div ng-transclude=""></div>
        </div>
    </demo2>
    
    分析
    1. 通过在指令中设置transclude=true,同时在template中包含<div ng-transclude>,实现了将元素内部元素移动到了ng-transclude元素内部,并创建了新的作用域

    示例三(link与compile)

    /*指令*/
    angular.module('app.directive.demo3',[]).directive('demo3Link',function(){
    return {
        restrict:'E',
        template:'<div>This is Demo3Link</div>',
        link:function(scope,iElement,iAttrs){
            iElement.html('<div>good link</div>');
        }
    }
    }).directive('demo3Compile',function(){
        return {
            restrict:'E',
            template:'<div>This is Demo3Compile</div>',
            compile:function(tElement,tAttrs,transclude){
                tElement.html('<div>test demo3 compile</div>');
                return function(scope,iElement,iAttrs){
                    //iElement.html('<div>good compile</div>');
                };
            }
        }
    });
    
    /*使用*/
    <demo3-link></demo3-link>
    <demo3-link></demo3-link>
    <demo3-compile></demo3-compile>
    
    /*页面生成的HTML*/
    <demo3-link><div>good link</div></demo3-link>
    <demo3-link><div>good link</div></demo3-link>
    <demo3-compile><div>test demo3 compile</div></demo3-compile>
    
    分析

    compile用于在编译期处理模板内容,并能设置preLink和postLink函数,此时将不能设置link函数,代码如下:

    compile:function(tElement,tAttrs,transclude){
        tElement.html('<div>test demo3 compile</div>');
        return {
            pre:function preLink(scope,iElement,iAttrs){
                console.log('preLink');
            },
            post:function postLink(scope,iElement,iAttrs){
                console.log('postLink');
            }
        };
    }
    

    link用于对替换后的元素进行操作,如果参数是iElement。


    示例四(简单加法计算器)

    /*代码在这里*/
    angular.module('app.directive.demo4',[]).directive('demo4',function(){
        return {
            restrict:'E',
            template:'<fieldset><legend>计算两个数之和</legend>' +
                '<div><input type="text" ng-model="num1">+<input type="text" ng-model="num2">=<span>{{total}}</span></div>' +
                '</fieldset>',
            replace:true,
            link:function(scope,iElement,iAttrs){
                scope.num1=0;
                scope.num2=0;
                scope.total=0;
                scope.$watch('num1+num2',function(to,from){
                    scope.total=+scope.num1+(+scope.num2)
                })
            }
        }
    });
    
    /*HTML在这里*/
    <demo4></demo4>、
    
    /*效果请自行测试*/
    
    分析

    可以利用指令完成特定的功能了。


    示例五(negHotkeys指令代码)

    代码在这里

    总结

    1. 指令依附于模块
    2. 一个模块可以有多个指令,但是需要采用示例三的写法
    3. 指令可以语义化标签,实现html组件化
    4. 其他...
  • 相关阅读:
    [转载]C#流,字节数组,字符串
    [C#错误]未找到类型或命名空间名称" " (是否缺少 using 指令或程序集引用?)
    批处理删除带空格的长目录或文件夹
    注释换行 引号内的字符串没有正确结束
    oracle sqlplus运行sql文件
    Target runtime Apache Tomcat v6.0 is not defined.错误解决方法
    Tomcat:Caused by: java.lang.OutOfMemoryError: PermGen space
    虚拟机vmware启动太快无法进入bios的解决方法
    MySQL Error 1130 Host 'localhost' is not allowed to connect to this MySQL server
    如何远程判断服务器的操作系统?
  • 原文地址:https://www.cnblogs.com/humin/p/4011470.html
Copyright © 2011-2022 走看看