前言

angular核心部分如下图几大块,最重要的莫过于指令这一部分,本文将重点讲解指令这一部分,后续笔者将通过陆续的学习来叙述其他如:factory、service等,若有叙述错误之处,欢迎各位指正以及批评。本文将通过一些实例来进行叙述。

话题

restrict以及replace

在sublimeText中安装angular插件之后,我们需要创建指令时此时将自动出现如下定义:所以我们将重点放在如下各个变量的定义。

.directive('', ['', function(){
// Runs during compile
return {
// name: '',
// priority: 1,
// terminal: true,
// scope: {}, // {} = isolate, true = child, false/undefined = no change
// controller: function($scope, $element, $attrs, $transclude) {},
// require: 'ngModel', // Array = multiple requires, ? = optional, ^ = check parent elements
// restrict: 'A', // E = Element, A = Attribute, C = Class, M = Comment
// template: '',
// templateUrl: '',
// replace: true,
// transclude: true,
// compile: function(tElement, tAttrs, function transclude(function(scope, cloneLinkingFn){ return function linking(scope, elm, attrs){}})),
link: function($scope, iElm, iAttrs, controller) { }
};
}]);

首先我们只需要知道一个属性【restrict】,意思是替换的是什么,【E】:元素,【A】:属性,【C】:类名,【M】:注释。template(模板)自然就不用说了。下面我们来看一个有关指令最简单的例子。

【1】脚本:

    var app = angular.module('app', []);
app.directive("hello",function(){
return{
restrict:"EACM",
template:"<h1>Hello</h1>"
}
});

【2】html:

    <hello></hello>
<div hello></div>
<p class="hello"></p>
<!-- directive:hello -->

此时的结果是四个带h1标签的Hello吗?显然不是,如下:

不是说好的将restrict的模式设置为【EACM】,理论上应该是显示四个,结果却不是。即使你设置了四个也只会显示三个,而注释不会显示,此时要设置另外一个属性即【replace:true】才会显示四个注释。同时也需要注意,在注释中的hello和后面的--之间要有间隔,你可以试试。

transclude

当我们替换的元素里面可能还嵌套者其他元素,而其他元素里面有内容,我们不希望被覆盖,此时就需要将transclude设置为true并将要应用的元素标记为ng-transclude。如下:

【脚本】:

    var app = angular.module('app', []);
app.directive("hello",function(){
return{
restrict:"EACM",
transclude:true,
template:"<h1>Hello<div ng-transclude></div></h1>",
}
});

【html】:

    <hello>
<div>博客园,你好</div>
</hello>

结果如下:

tepmlateUrl

在实际开发中用template形式来给出模板似乎不太友好,一旦替换的内容比较多那么显得代码比较凌乱,此时我们就要用到templateUrl,将模板单独写在一个页面即可。这个就不用说了,在这个内容不得不说的是模板的缓存。

【脚本】:

    var app = angular.module('app', []);
app.run(function($templateCache){
$templateCache.put("hello.html","<h1>hello cnblogs</h1>")
});
app.directive("hello",function($templateCache){
return{
restrict:"AE",
template:$templateCache.get("hello.html"),
replace:true
};
});

【html】:

<hello></hello>

结果如下:

scope

在接触这个属性之前我们首先来看看一个例子。

【脚本】:

    var app = angular.module('app', []);
app.directive("hello",function(){
return{
restrict:"AE",
template:'<div><input type="text" ng-model="test"/>{{test}}</div>',
replace:true
};
});

【html】:

    <hello></hello><br/>
<hello></hello><br/>
<hello></hello>

我们来瞧瞧结果:

我们将鼠标放在第一个文本框输入xpy0928,下面两个同样也发生相应的改变,我们再试试将鼠标聚焦于第二个看看其他两个的改变如何:

由上知,同样如此,貌似三个文本框的作用域是一样的,一变都变,相互影响。在指令中,当我们需要保持各自的作用域时,此时就需要【scope】属性,并设置为true。我们再来试试

require

【指令与页面上已定义控制器进行交互】

在开始这个话题之前我们先看看指令与已定义的控制器如何进行交互?【注意是在页面上已定义的控制器】

【脚本】:

    var app = angular.module('app', []);
app.controller("ctrl",["$scope",function($scope){
$scope.win = function(){
alert("你赢了");
}
}])
app.directive("lay",function(){
return{
restrict:"AE",
scope:true,
template:'<div>点击我,有惊喜哦</div>',
replace:true,
link:function(scope,elment,attr){
elment.on("click",function(){
scope.win();
})
}
};
});

【html】:

    <div ng-controller="ctrl" style="background-color:orange">
<lay></lay>
</div>

对于页面中已定义的控制器,指令为与其进行交互直接通过link上的scope来获取该控制器上的APi即可。

【指令与指令上控制器进行交互】

此时就需要用到require,此属性的作用是指令与指令之间的交互,说的更加具体一点就是与其他指令中控制器之间的交互。在指令中获取其他指令的控制器要用到link函数的第四个参数,link函数的前三个参数还是非常容易理解,不再叙述。那么是怎样在当前指令去获取该控制器呢?这时就需要用到require属性。

(1)require的值用?、^、或者?^修饰。

(2)如果不用任何修饰,则在当前指令中进行查找控制器。

(3)如果用^修饰,则在当前指令的父指令进行查找控制器,若未找到,则会抛出异常。

(4)如果用?修饰,则说明在当前指令中未找到控制器,此时将以null作为第四个参数。

(5)如果需要交互多个指令,则以数组形式给出,如:[^?a,^?b]。

鉴于此,为了不抛出异常,我们一般以^?来进行修饰。

就上面解释,我们来看一个例子,如下:

【脚本】:

    var app = angular.module('app', []);
app.directive('customdirective', function(){
return {
controller: function($scope, $element, $attrs, $transclude) {
var self = this;
$scope.count = 0;
self.add = function(){
$scope.$apply(function(){
$scope.count++;
})
}
},
restrict: 'E',
};
}).directive('childirective', function(){
return {
require: '^customdirective',
restrict: 'E',
template: '<button id="add">点击增加1</button>',
replace: true,
link: function($scope, iElm, iAttrs, controller) {
angular.element(document.getElementById("add")).on("click",controller.add);
}
};
})

【html】:

<customdirective>
<div>次数:{{count}} </div>
<br/>
<childirective></childirective>
</customdirective>

对于指令上的link与指令上的controller的何时使用,我们可以这样概括:当一个指令上想向外部暴露这个指令时,此时利用controller进行暴露,而其他指令需要利用指令时,通过属性require和link上的第四个参数进行获取暴露指令的APi,否则的话我们不需要第四个参数。

那么问题来了,指令的作用到底是什么呢?

假如我们有几个控制器都需要用到相同指令但是对应不同事件时,此时难道需要定义不同的指令吗?答案肯定很显然不是,指令说到底就是为了【复用】。下面我们继续来看一个例子。

【脚本】:

    var app = angular.module('app', []);

    app.controller("first",["$scope",function($scope){
$scope.first = function(){
alert("第一个控制器函数");
}
}]) app.controller("second",["$scope",function($scope){
$scope.second = function(){
alert("第二个控制器函数");
}
}]) app.directive('lay', function(){
return{
restrict:"AE",
link:function(scope,element,attr){
element.on("click",function(){
scope.$apply(attr.loader);
})
}
};
});

【html】:

<div ng-controller="first">
<lay loader="first()">第一个控制器</lay>
</div>
<br/>
<div ng-controller="second">
<lay loader="second()">第二个控制器</lay>
</div>

 当需要复用指令时,可以通过获取指令上属性对应的方法,最终利用apply方法应用到对应的控制器中。

结语

在这里我们稍微详细的叙述了指令中有关属性的用法,对于一些原理性的东西,毕竟不是做前端的,所以没有做过多的探讨。下面我们最后以一个实例来结束本文。

通过指令来使未验证通过的文本框聚焦。

【脚本】:

    var app = angular.module('app', []);
app.controller('ctrl', function ($scope, $location, $rootScope) {
})
app.directive("parentDirective", function () {
return {
restrict: 'A',
require: ['form'],
controller: function () {
// nothing here
},
link: function (scope, ele, attrs, controllers) {
var formCtrl = controllers[0];
}
};
}).directive('input', function () {
return {
restrict: 'E',
priority: -1000,
require: ['^?parentDirective', '^?angularValidator'],
link: function (scope, elm, attr, ctrl) {
if (!ctrl) {
return;
} elm.on('focus', function () {
elm.addClass('apply-focus'); scope.$apply(function () {
ctrl.hasFocus = true;
});
}); elm.on('blur', function () {
elm.removeClass('apply-focus');
elm.addClass('apply-visited'); scope.$apply(function () {
ctrl.hasFocus = true;
ctrl.hasVisited = true; });
}); }
};
});

【html】:

 <form  ng-controller="ctrl" novalidate angular-validator >
<div class="gloabl-form-content"> <div class="row">
<div class="col yellow-divider">
<div class="col-first">
<label><span style="color:red;">*</span>姓名</label>
</div>
<div class="col-second">
<input name="name"
type="text"
ng-model="profile.name"
validate-on="blur"
ng-pattern="/^[ a-zA-Z]*$/"
required
required-message="'请输入姓名.'"
ng-message="'不能输入数字'"
maxlength="100" />
</div> <div class="col-third">
<label>住址</label>
</div>
<div class="col-four">
<input name="addr" type="text" ng-model="profile.addr"
validate-on="blur"
ng-pattern="/^[ a-zA-Z]*$/"
invalid-message="'不能输入数字'"
maxlength="100" />
</div>
</div>
</div>
<div class="row">
<div class="col yellow-divider">
<div class="col-third">
<label><span style="color: red;">*</span>手机号码</label>
</div>
<div class="col-four">
<input type="text"
ng-model="customer.number"
validate-on="blur"
ng-pattern="/^[ 0-9.]*$/"
required
required-message="'请输入手机号码'"
invalid-message="'只能输入数字'" />
</div>
</div>
</div> </div>
</form>

效果(1):

效果(2):

【擦,不行,快冻成傻逼了,手冻僵了,不能写了,就到这里诺。。。。。。。。。。】

AngularJS之Directive(三)的更多相关文章

  1. angularJS中directive父子组件的数据交互

    angularJS中directive父子组件的数据交互 1. 使用共享 scope 的时候,可以直接从父 scope 中共享属性.使用隔离 scope 的时候,无法从父 scope 中共享属性.在 ...

  2. AngularJS之directive

    AngularJS之directive AngularJS是什么就不多舌了,这里简单介绍下directive.内容基本上是读书笔记,所以如果你看过<AngularJS up and runnin ...

  3. Angularjs之directive指令学习笔记(二)

    1.Directive的五个实例知道driective作用.其中字段restrict.template. replace.transclude.link用法 参考文章链接地址:http://damoq ...

  4. 前端angularJS利用directive实现移动端自定义软键盘的方法

    最近公司项目的需求上要求我们iPad项目上一些需要输入数字的地方用我们自定义的软键盘而不是移动端设备自带的键盘,刚接到需求有点懵,因为之前没有做过,后来理了一下思路发现这东西也就那样.先看一下实现之后 ...

  5. Angularjs的directive封装ztree

    一般我们做web开发都会用到树,恰好ztree为我们提供了多种风格的树插件. 接下来就看看怎么用Angularjs的directive封装ztree <!DOCTYPE html> < ...

  6. angularjs学习笔记三——directive

    AngularJS 通过被称为 指令 的新属性来扩展 HTML. 正如你所看到的,AngularJS 指令是以 ng 作为前缀的 HTML 属性. HTML5 允许扩展的(自制的)属性,以 data- ...

  7. AngularJS中Directive指令系列 - scope属性的使用

    文章是转的,我做下补充.原文地址:https://segmentfault.com/a/1190000002773689 每当一个指令被创建的时候,都会有这样一个选择,是继承自己的父作用域(一般是外部 ...

  8. 通过angularjs的directive以及service来实现的列表页加载排序分页

    前两篇:(列表页的动态条件搜索,我是如何做列表页的)分别介绍了我们是如何做后端业务系统数据展示类的列表页以及动态搜索的,那么还剩下最重要的一项:数据展示.数据展示一般包含三部分: 数据列头 数据行 分 ...

  9. 通过angularjs的directive以及service来实现的列表页加载排序分页(转)

    前两篇:(列表页的动态条件搜索,我是如何做列表页的)分别介绍了我们是如何做后端业务系统数据展示类的列表页以及动态搜索的,那么还剩下最重要的一项:数据展示.数据展示一般包含三部分: 数据列头 数据行 分 ...

随机推荐

  1. php获取网卡MAC地址源码

    <?php /** 获取网卡的MAC地址原码:目前支持WIN/LINUX系统 获取机器网卡的物理(MAC)地址 **/ class GetMacAddr{ var $return_array = ...

  2. [LintCode] Sort List 链表排序

    Sort a linked list in O(n log n) time using constant space complexity. Have you met this question in ...

  3. swiper的初步使用

    1.引入文件,顺序引入(此处基于jquery,且版本至少1.7以上) <link rel="stylesheet" href="path/to/swiper-3.4 ...

  4. PDF转JPG

    问题:对于上次解决PB调用不起PDF插件的问题,所以将PDF转换为HTML.但是转换完之后发现一个问题,pdf2htmlEX插件转换出的html只支持IE9以上,IE9以下的都会各式错乱, 所以只能换 ...

  5. USACO翻译:USACO 2013 JAN三题(1)

    USACO 2013 JAN 一.题目概览 中文题目名称 镜子 栅栏油漆 奶牛排队 英文题目名称 mirrors paint lineup 可执行文件名 mirrors paint lineup 输入 ...

  6. 用微信小程序开发的Canvas绘制可配置的转盘抽奖

    使用https://github.com/givebest/GB-canvas-turntable代码移植过而来. 其它 微信小程序感觉是个半成品,代码移植过程比较繁琐麻烦.canvas API 部分 ...

  7. nlp

    http://blog.sina.com.cn/s/blog_574a437f01019poo.html

  8. viso

  9. SQL Server2008清除数据库日志

    m缪国瑞  11:10:17 --'这里的DNName_Log 如果不知道在sys.database_files里是什么名字的话,可以用以下注释的语句进行查询USE dochuanGOSELECT f ...

  10. 为什么要重写hashcode() 方法

    Java中的集合(Collection)有两类,一类是List,再有一类是Set. 前者集合内的元素是有序的,元素可以重复:后者元素无序,但元素不可重复. 那么我们怎么判断两个元素是否重复呢? 这就是 ...