《AngularJs权威指南》读书笔记---指令

《AngularJs权威指南》

记得最开始学习ionic混合开发的时候, 朋友们都推荐我先学学angular.js, 然后再看ionic框架的东西; 现在想来也确实, ionic框架基本都是UI相关的知识, 并不难, 而页面里面涉及到angular.js的各种逻辑才是真正能让一个人成为大牛的知识;

选这本书就是因为朋友们都推荐这本, 而且讲的还不错, 最重要的是他们有资源, O(∩_∩)O哈哈~

首先介绍一下本书中关于指令的知识结构:

AngularJs权威指南之指令思维导图

一. 指令简介

用过HTML的都知道, 往往在实现一些特殊功能的时候, 原有的HTML标签并不完全能满足设计要求, 这时候指令就派上用场了; 指令本质上就是扩展一些自定义的HTML元素以实现一些特定的功能;

二. 内置指令

AngularJS事实上也是在原生JS的基础上进行一些扩展和优化, 自然就会包括一些自定义的内置指令; 除了form和a等一些重载了原生的HTML元素, 其他的内置指令通常以ng作为前缀; 这样做的目的也是对原生的一种优化, 比如常用的href指令, 无论里面的链接是可用还是, 不可用的, 当调用href的时候, 就会直接返回调用结果; 而ng-href指令则是当里面的表达式调用并且返回一个值的时候才开启, 否则会是一个禁用状态; 当然既然人家官方用ng这个前缀, 你就不要跟人家抢了, 换一个, 大家和谐一点儿;

有网友总结了一下AngularJS的内置指令, 一共有63个;

简单介绍一下form指令:

<form>
First name:</br>
<input type="text" name="firstname" value="huo">
<br>
Last name:</br>
<input type="text" name="lastname" value="yu">
<br><br>
<input type="submit" value="Submit">
</form>

效果图:

要注意一下几点:

  • HTML原生的form表单是不能嵌套的, 但Angular封装后可以嵌套
  • Angular为form扩展了自动校验, 防止重复提交等功能
  • Angular对input元素的type进行了了扩展, 一共提供一下10中类型:
    text, number, url, email, radio, checkbox, hidden, button, submit, reset;
  • Angular为表单内置了4种CSS样式
    ng-valid, ng-invalid, ng-pristine, ng-dirty;
  • 内置校验器: require, minlength, maxlength

三. 指令详解

1. 指令定义

本书中对指令的定义是在特定DOM元素上运行的函数, 指令可以扩展这个元素的功能;
在Angular中是通过directive()这个模块来定义指令的;而directive()可以接受两个参数:

  • name
    指令的名字
  • factory_function(函数)
    这个函数定义了指令的行为
 angular.application('myApp', [])
     .directive('myDirective', function() {
     //  一个指令定义对象
     return {
             //  通过设置项来定义指令, 在这里进行填写
            };
});

在HTML中调用就行:

<div my-directive></div>
2. 指令函数介绍

2.1 restrict(字符串)

这些选项可以单独使用, 也可以混合使用;

2.2 优先级(数值型)
由于考虑到性能问题, ngRepeat被设置成所有内置指令中优先级最高的; 当然如果两个元素的优先级一样, 会执行先声明的那个;

2.3 terminal(布尔型)
它用来告诉AngularJs停止运行当前元素上比本指令优先级低的指令, 但当优先级相同的情况还是会运行;
例如:ngView和ngIf, ngIf的优先级略高于ngView, 如果ngIf表达式为true, ngView就可以被正常执行; 但如果ngIf的表达式为false, ngView就不会被执行;

2.4 template(字符串或函数)
template参数必须被设置成以下两种形式之一:

  • 一段HTML文本
  • 一个可以接受两个参数的的函数, 参数为tElement和tAttrs, 并返回一个代表模板的字符串;

2.5 templateUrl(字符串或函数)
templateUrl参数可以是以下形式:

  • 一个代表外部HTML文件的路径字符串
  • 一个可以接受两个参数的的函数, 参数为tElement和tAttrs, 并返回一个代表模板的字符串;

2.6 replace(布尔型)
replace是个可选参数, 默认为false; 当设置为true后

.directive('someDirective', function() {
         return {
             replace: true
             template: '<div>looking for something<div>'
                };
 });

输出结果为:

<div>looking for something<div>

2.7 scope参数(布尔型或对象)
scope参数有三种取值方式;
2.7.1 false(默认值)
直接使用父scope, 内部并没有一个新的scope,它和指令以外的代码共享同一个scope。
①指令

app.directive('myDirective', function() {
    return {
        restrict: 'E',
        replace: true,
        templateUrl: '../templates/my_template.html',
        scope: false,   // 默认值
        controller: null
    }
});

②指令模板(my_template.html)

<div>
    <!--这里ng-model绑定的input,就是父scope的变量input-->
    <p>自定义指令scope:<input type="text" ng-model="input"></p>
    <p>结果:{{input}}</p>
</div>

③指令的使用(index.html)

<body ng-app="scopeTest" ng-controller="scopeTestStr">
    <p>父scope:<input type="text" ng-model="input"></p>
    <!--自定义指令-->
    <my-directive></my-directive>
</body>

效果如下:

2.7.2 true(继承父scope)
当设置为true的时候, 会从父作用域继承并创建一个新的作用域对象;
参照值为false的情况, 只是将值改为true; 效果如下:

2.7.3 { }
创建一个新的"隔离"scope,但仍可与父scope通信;
隔离的scope,通常用于创建可复用的指令,也就是它不用管父scope中的model。然而虽然说是“隔离”,但通常我们还是需要让这个子scope跟父scope中的变量进行绑定。绑定的策略有3种:

①@ 单项绑定

<body ng-app="scopeTest">
    <!--外部scope-->
    <p>父scope:<input type="text" ng-model="input"></p>
    <!--内部隔离scope-->
    <my-directive my-text="{{input}}"></my-directive>

    <script>
        var app = angular.module('scopeTest', []);
        app.directive('myDirective', function () {
            return {
                restrict: 'E',
                replace: true,
                template: '<p>自定义指令scope:<input type="text" ng-model="myText"></p>',
                scope: {
                    myText: '@'
                }
            }
        });
    </script>
</body>

效果图:

②= 双向绑定

<body ng-app="scopeTest">
    <!--外部scope-->
    <p>父scope:<input type="text" ng-model="input"></p>

    <!--内部隔离scope-->
    <!--注意这里,因为是双向绑定,所以这里不要“{{}}”这个符号-->
    <my-directive my-text="input"></my-directive>

    <script>
        var app = angular.module('scopeTest', []);
        app.directive('myDirective', function () {
            return {
                restrict: 'E',
                replace: true,
                template: '<p>自定义指令scope:<input type="text" ng-model="myText"></p>',
                scope: {
                    myText: '=' // 这里改成了双向绑定
                }
            }
        });
    </script>
</body>

效果图:

③& 内部scope的函数返回值和外部scope绑定

<body ng-app="scopeTest">
    <!--外部scope-->
    <p>父scope:<input type="text" ng-model="input"></p>

    <!--内部隔离scope-->
    <!--注意这里,函数名字也要用 连字符命名法-->
    <my-directive get-my-text="input"></my-directive>

    <script>
        var app = angular.module('scopeTest', []);
        app.directive('myDirective', function () {
            return {
                restrict: 'E',
                replace: true,
                template: '<p>结果:{{ getMyText() }}</p>',
                scope: {
                    getMyText: '&' // 这里改成了函数返回值的绑定
                }
            }
        });
    </script>
</body>

效果图:

2.8 transclude(布尔型)
默认为false; 只有当你希望创建一个可以包含任意内容的指令的时候才会为true; 代码如下所示:

app.directive('myDirective', function() {
    return {
        restrict: 'AE',
        transclude: true,
        template: "<div> hellow angular ! <div ng-transclude></div></div>"
    }
});

2.9 controller(字符串或函数)
指令内部的controller, 暴露一些public方法给内部指令使用;
①字符串;

     angular.module('myApp', [])
       .directive('myDirective',  function() {
          restrict: 'A', // 始终需要
          controller: 'SomeController'
     })

     // 在应用中其他地方定义该控制器
     angular.module('myApp')
        .controller('SomeController', function($scope, $element, $attrs, $transclude) {
             // 控制器逻辑
     });

②函数
可以是指令内部通过匿名构造函数的方式来定义一个内联的控制器;

 angular.module('myApp',[])
     .directive('myDirective', function() {
         restrict: 'A',
         controller:
         function($scope, $element, $attrs, $transclude) {
               // 控制器逻辑
        }
});

现在你也可以知道, 控制器中还有其他一些特殊的服务可以注入到指令中, 这些服务有:

  • $scope 指令对应的作用域
  • $element 指令对应的元素
  • $attrs 当前元素属性组成的对象
  • $transclude 嵌入链式函数会与对应的嵌入作用域进行预绑定

在控制器内部操作DOM和angular.js风格相悖的做法, 但通过链式函数就可以实现这个需求; 例如在compile参数中使用transcludeFn是推荐的做法;

本文提供了一个添加超链接的例子:

 angular.module('myApp')
     .directive('link', function() {
      return {
          restrict: 'EA',
          transclude: true,
          controller:
               function($scope, $element, $transclude, $log) {
               $transclude(function(clone) {
                    var a = angular.element('<a>');
                    a.attr('href', clone.text());
                    a.text(clone.text()); 8 $log.info("Created new a tag in link directive");
                    $element.append(a);
               });
          }
      };
});

link函数可以与控制器指令的控制器互换; 控制器用来提供指令间的复用行为, 但链接函数只能在当前内部指令中定义行为且无法在指令间复用;

link函数可以将指令互相隔离, 而controller则定义可复用的行为;

下面附一张link函数与compile函数的比较图:

2.10 require(字符串或数组)
字符串或数组的值会是当前指令作用域中使用的指令名称, 即用来调用暴露的内部方法;

对于指令的学习, 书中提供了内部原理, 当然光这些还是远远不够, 附上一个第三方指令库, 看看源码, 体验一下别人是怎么写的;
AngularUI

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容