angularjs 模块restrict 有哪些模块

创建自定义 AngularJS 指令:Part 4 transclude和restrict介绍
在本系列的第3篇文章中,我介绍了指令中定义的孤立作用域属性怎样传递参数给外部函数(初看起来需要一些技巧,一旦掌握要点就变得很简单了)。在这篇文章中,我将将继续介绍相关自定义指令的知识,主要介绍transclude和restrict这两个指令参数,看看它们有什么功能,以及怎样使用。
指令中的restrict
在HTML中,指令可以被定义为元素、属性、类、注释。你怎样限定你的自定义指令使用方式呢?
可以使用restrict接口属性来规定自定义指令在HTML中怎么使用、在哪使用。这个接口属性的值有下边几种:
restrict的值
当做元素使用。示例:
当做元素属性使用。示例:
当做元素上的样式类使用。示例:
当做注释使用(很少使用)。示例:
下边是一个指令用作元素或属性的例子。注意,这两个值之间没有被隔开。
app.directive('myDirectiveWithRestriction', function () {
restrict: 'EA',
tasks: '='
即使C和M值也可以使用,但很少用到。大多数指令只使用E和A。现在,你已经了解了restrict,下边让我们看transclude的概念。
指令中的transclude
我第一次听到这个词&transclusion&,我怀疑它是不是一个真正的单词(如果你已经在YouTube上看到我在AngularJS分钟60ish视频,你就会知道这是真的)。如果你在一个网络字典中查找这个单词,你不会找到任何东西,但定义可以在维基百科等网站上找到。大多数的网站定义&transclusion&以下列方式:
通过引用的方式包含文档或文档的一部分到另一个文档(见维基百科)。
如果你曾经加载CSS样式表或HTML模板(HTML5更新的功能)到HTML页面或加载的页眉或页脚的HTML片段到服务器端页面(通常称为服务器端包括),那么你已经使用transclusion的方法了。这里有一个简短的视频,提供transclusion的快速概览:(视频见原文)
对于AngularJS来说,transclude(transclusion 的动词形式)提供了一种定义插入指令的模板和展示这个模板的方法。例如:你可能会有一个需要输出一个表格的指令,并且允许使用指令的人控制怎样渲染表格行。或者,你可能会有一个输出一条错误信息的指令,并且指令的使用者可以控制HTML内容和使用不同渲染颜色。通过这些类型的功能,指令使用者可以有更多的控制权,去控制指令生成的HTML各个部分如何渲染。
要支持替换,有两个要点必须掌握。第一个要点是使用transclude属性在指令中,在HTML中,自定义指令内部还有其它DOM时,如果transclude属性设置为false,指令内定义的模板将会替换掉指令内部的DOM;如果transclude属性设置为false,将会把这些DOM放到指令内部模板中ng-transclude指令所在的地方,如果没有写ng-transclude,这些DOM也将不会出现在页面中。第二个要点是ng-transclude指令,它是AngularJS内部指令,它被用来决定在一个指令模板中哪个地方嵌入外部内容。下边的指令代码,使用这两个要点实现替换。
原始的内容,
还会在这里。
&script src=../../lib/angular.js&&/script&&script src=../../lib/jquery.js&&/script&&script&
var app = angular.module('directivesModule', []);
app.directive('hello', function() {
restrict: 'E',
template: 'Hi there ',
transclude: true,
replace:false
运行效果如下:
原始的内容,
还会在这里。 Hi there
在这个例子中,还可以看到有个replace属性,当这个属性设置为true时,将会使用模板替换掉页面中标签所在的DOM(示例中的hello标签);设置为false时,将会把模板放到标签内部。
一旦你理解了transclude的使用方法,它将会变得很简单。就像视频中提到的,服务器端包含或者CSS样式单嵌入网页的概念与transclude类似。在指令中使用transclude 和ng-transclude,你可以使你的指令具有定制功能。
到这里,自定义指令系列是否结束了?不幸的是,没有结束。当指令模板中包含ng-repeat 或ng-if 时,transclude将会变得很复杂。我将会在接下来的文章中介绍如何处理这些场景。Angular 常用指令实例总结整理
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了Angular 常用指令实例总结整理的相关资料,本文整理了常用指令,大家可以参考使用,需要的朋友可以参考下
Angular 常用指令
已经用了angular很久积累了一些很实用的指令,需要的话直接拿走用,有问题大家一起交流
1.focus时,input:text内容全选
angular.module('my.directives').directive('autoselect', [function () {
restrict: 'A',
link: function (scope, element, attr) {
if (element.is("input") && attr.type === "text") {
var selected =
var time = parseInt(attr["autoselect"]);
element.bind("mouseup", function (e) {
if (selected) {
e.preventDefault();
e.stopPropagation();
selected =
if (time & 0) {
element.bind("focus", function (event) {
setTimeout(function () {
selected =
event.target.select();
element.bind("focus", function (event) {
selected =
event.target.select();
2.clickOutside指令,外部点击时触发,click-outside="func()" func为自己指定的方法,一般为关闭当前层的方法,inside-id="" 点击指定id的输入框时,当前层不关闭
angular.module('my.directives').directive('clickOutside', ['$document', function ($document) {
restrict: 'A',
link: function (scope, element, attrs) {
$(element).bind('mousedown', function (e) {
e.preventDefault();
e.stopPropagation();
$("#" + attrs["insideId"]).bind('mousedown', function (e) {
e.stopPropagation();
$("#" + attrs["insideId"]).bind('blur', function (e) {
setTimeout(function () {
scope.$apply(attrs.clickOutside);
$document.bind('mousedown', function () {
scope.$apply(attrs.clickOutside);
3.clickInside指令,内部点击时触发
angular.module('my.directives').directive('clickInside', ['$document', function ($document) {
restrict: 'A',
link: function (scope, element, attrs, ctrl) {
$(element).bind('focus click', function (e) {
scope.$apply(attrs.clickInside);
e.stopPropagation();
4.scrollInside 指令 ,内部滚动时触发
angular.module('my.directives').directive('scrollInside', function () {
restrict: 'A',
link: function (scope, element, attrs, ctrl) {
$(element).bind('scroll', function (e) {
scope.$apply(attrs.scrollInside);
e.stopPropagation();
5. bindKeyBoardEvent指令,内部获得焦点或者点击时触发
angular.module('my.directives').directive('bindKeyBoardEvent', function () {
restrict: 'A',
link: function (scope, element, attrs, ctrl) {
$(element).bind('focus click', function (e) {
scope.$apply(attrs.bindKeyBoardEvent);
e.stopPropagation();
6. myDraggable 使元素可拖动
angular.module('my.directives').directive('myDraggable', ['$parse', function ($parse) {
restrict: 'A',
link: function (scope, element, attr) {
if (attr["modal"] !== undefined) {
scope.$watch(attr["modal"], function (newValue) {
if (newValue) {
setTimeout(function () {
$(".modal").draggable({handle: ".modal-header"});
$(".modal").attr("style", "");
$(window).resize(function () {
$(".modal").attr("style", "");
element.draggable($parse(attr["hrDraggable"])(scope));
6.myResizable 使元素可拖拽改变尺寸大小
angular.module('my.directives').directive('myResizable', ['$parse', function ($parse) {
restrict: 'A',
link: function (scope, element, attr) {
if (attr["modal"] !== undefined) {
scope.$watch(attr["modal"], function (newValue) {
if (newValue) {
setTimeout(function () {
$(".modal").resizable({handles: "e, w"});
element.resizable($parse(attr["hrResizable"])(scope));
6. conditionFocus 作为一个元素的属性存在:如果监听的表达式值为true,则将焦点放到本元素上。
angular.module('my.directives').directive("conditionFocus", [function () {
return function (scope, element, attrs) {
var dereg = scope.$watch(attrs.conditionFocus, function (newValue) {
if (newValue) {
element.focus();
element.bind("$destroy", function () {
if (dereg) {
7.scrollToHide 滚动到顶部的时候触发
angular.module('my.directives').directive("scrollToHide", [function () {
return function (scope, element, attrs) {
var height= parseFloat(attrs.maxHeight)
$(window).scroll(function(){
var scrollTop= document.body.scrollTop||document.documentElement.scrollT
if(scrollTop&height){
$parse(attrs.ngShow).assign(scope, false);
$parse(attrs.ngShow).assign(scope, true);
8.resetToZero 作为一个元素的属性存在:如果监听的表达式值为true,则将本元素中所绑定的ngModel值设为0
angular.module('my.directives').directive("resetToZero", ["$parse", function ($parse) {
return function (scope, element, attrs) {
var dereg = scope.$watch(attrs.resetToZero, function (newValue) {
if (newValue) {
if (attrs.ngModel) {
$parse(attrs.ngModel).assign(scope, 0);
element.bind("$destroy", function () {
if (dereg) {
9.resetToEmptyString 作为一个元素的属性存在:如果监听的表达式值为true,则将本元素中所绑定的ngModel值设为空字符串。
angular.module('my.directives').directive("resetToEmptyString", ["$parse", function ($parse) {
return function (scope, element, attrs) {
var dereg = scope.$watch(attrs.resetToEmptyString, function (newValue) {
if (newValue) {
if (attrs.ngModel) {
var _getter = $parse(attrs.ngModel);
if (_getter(scope)) {
_getter.assign(scope, "");
_getter.assign(scope.$parent, "");
element.bind("$destroy", function () {
if (dereg) {
10. numberOnly 输入框内容仅限数值的指令(输入内容不允许为 负值),可以设定最大值(max属性)
angular.module('my.directives').directive("numberOnly", ["$parse", function ($parse) {
return function (scope, element, attrs) {
element.bind("keyup", function () {
if(event.keyCode==37||event.keyCode== 39){
var val = element.val().replace(/[^\d.]/g, '');
if(attrs.max){
if(val&parseInt(attrs.max)){
val=attrs.
element.val(val);
if (attrs.ngModel) {
$parse(attrs.ngModel).assign(scope, val);
element.bind("afterpaste", function () {
var val = element.val().replace(/[^\d.]/g, '');
if(attrs.max){
if(val&parseInt(attrs.max)){
val=attrs.
element.val(val);
if (attrs.ngModel) {
$parse(attrs.ngModel).assign(scope, val);
11. upperCaseOnly 输入框自动转换成大写
angular.module('my.directives').directive("upperCaseOnly", ["$parse", function ($parse) {
return function (scope, element, attrs) {
element.bind("keyup", function () {
var val = element.val().toUpperCase();
element.val(val);
if (attrs.ngModel) {
$parse(attrs.ngModel).assign(scope, val);
element.bind("afterpaste", function () {
var val =element.val().toUpperCase();
element.val(val);
if (attrs.ngModel) {
$parse(attrs.ngModel).assign(scope, val);
12. noSpecialString 输入框内容不能为特殊字符
angular.module('my.directives').directive("noSpecialString", ["$parse", function ($parse) {
return function (scope, element, attrs) {
element.bind("keyup", function () {
var val = element.val().replace(/[\W]/g, '');
element.val(val);
if (attrs.ngModel) {
$parse(attrs.ngModel).assign(scope, val);
element.bind("afterpaste", function () {
var val = element.val().replace(/[^\d]/g, '');
element.val(val);
if (attrs.ngModel) {
$parse(attrs.ngModel).assign(scope, val);
13. round2bit 输入框失去焦点 保留两位小数
angular.module('my.directives').directive("round2bit", ['$parse', '$filter', function ($parse, $filter) {
return function ($scope, element, attrs) {
element.blur(function () {
if (attrs.ngModel) {
var _getter = $parse(attrs.ngModel);
var _numberStr2Round = (_getter($scope) || 0);
_getter.assign($scope, $filter('number')(_numberStr2Round, 2).split(",").join(""));
$scope.$apply();
14.SelfHeight dom编译期设置元素高度,可以接受数字或者表达式
angular.module('hr.directives').directive('SelfHeight', ['$timeout', function ($timeout) {
function _resizeElement(element, SelfHeight) {
element.height((typeof SelfHeight === "number") ? SelfHeight : eval(SelfHeight));
priority: 1000,
link: function (scope, element, attrs) {
var hrSelfHeight = attrs["SelfHeight"];
var on = attrs["on"];
$(window).resize(function () {
_resizeElement(element, scope.$eval(SelfHeight));
scope.$watch(on, function () {
$timeout(function () {
_resizeElement(element, scope.$eval(SelfHeight));
$(window).resize(function () {
_resizeElement(element, SelfHeight);
_resizeElement(element, SelfHeight);
&感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具上一章节,给大家回顾了一下AngularJS指令参数的基础使用。如果有纰漏,欢迎大家给我留言,相互探讨探讨。
指令化,其实本质就是代码的通用化与模块化,AngularJS的指令化工作,将逻辑与DOM都结合在一起,能够做到即插即用,与Asp的Component是相似的概念。
要做到模块化,必要的要求就是通用代码与业务代码的解耦。而解耦并不代表完全的隔绝,解耦要做的是,通用模块与业务模块的隔离,同时也保留接口提供两者通讯。
啰嗦,赶紧实例吧!
某天,产品老大压下来需求,要做个学生信息填写卡,说白了就是一个表单编辑器,so easy,前端单身狗拍拍脑袋马上开工。
&div ng-controller='demoCtrl'&
&div class="panel"&
&h3&student card&/h3&
&span&name:&/span&
&input type="text" ng-model="stu.name" /&
&span&sexy :&/span&
&select ng-model="stu.sexy"&
&option value="1"&male&/option&
&option value="2"&female&/option&
&p&......&/p&
&button class="btn btn-info" type="button" ng-click="saveEditing()"&save&/button&
var app = angular.module("app", []);
app.controller('demoCtrl', function ($scope) {
$scope.stu = {
name: "mark",
$scope.saveEditing = function () {
//$http.post("...", { stu: $scope.guy });
console.log($scope.guy.name + " is saving!");
console.log($scope.guy);
//这里省略信息卡交互逻辑……
出来结果,还行。
隔了一天,产品老大想了想,要增强体验,在选择性别的时候,名称要根据男女颜色变化;输入名称的时候,要自动匹配近似名称,并且首字母大写。行,改呗。demoCtrl加上以下逻辑
$scope.nameChange = function () {
//处理名称变更
$scope.sexyChange = function () {
//处理性别变更
又隔了一天,产品老大终于定稿,这个学生信息填写卡,要应用到demo页、demo1页、demo2页上,而3个页面保存功能指向的后端接口都不一样。
前端单身狗:虽然不至于问候您大爷,但至少要好好考虑如何实现才省功夫吧。难道要把demoCtrl的相关代码都copy到另外两个页面吗?这个时候,只要是写过代码的同志都会say no吧!
赶紧指令化。
首先,把信息卡的DOM结构独立开来,创建指令student。指令scope参数要设为{},如果设为false、true达不到完全隔离的效果哦,不理解原因的童鞋请回顾上一章节。
&div ng-controller='demoCtrl'&
&student&&/student&
&div ng-controller='demo1Ctrl'&
&student&&/student&
&div ng-controller='demo2Ctrl'&
&student&&/student&
&!--信息卡DOM模板-&
&script type="text/html" id="t1"&
&div class="panel"&
&span&name:&/span&
&input type="text" ng-model="stu.name" /&
&span&sexy :&/span&
&select ng-model="stu.sexy"&
&option value="1"&male&/option&
&option value="2"&female&/option&
&button class="btn btn-info" type="button" ng-click="onSave()"&save&/button&
var app = angular.module("app", []);
app.directive('student', function () {
restrict: 'E',
scope: {},
template: function (elem, attr) {
return document.getElementById('t1').innerHTML;
controller:function($scope){
//这里省略信息卡交互逻辑……
虽然独立了信息卡代码,但有两个问题是显而易见的
隔离以后,指令内部如何获得3个demoCtrl的stu?
保存按钮又是如何调用外部3个demoCtrl不同的save方法?
问题其实指明了解决思路,student需要两个接口与外部通讯:scope.stu & scope.save()
为大家介绍3种通讯方案。
指令scope {}参数,可以完全隔离作用域,但是也预留了3种绑定策略,实现子域与父域通讯。
为指令建立两个通讯接口,stu采取=双向绑定父域对象的策略;而onSave则采取$反向调用父域函数策略。
//=为双向绑定策略
onSave: '&'
//$反向调用父域函数策略
优点:简单、简洁缺点:
通讯接口要求比较多、复杂的情况下,指令scope {}要配置的绑定策略也比较多;
造成指令与指令之间的通讯容易混乱;
指令内部好像没有办法,往onSave()函数里面传参,这个不确定,求助大家。
&student stu="guy" on-save="saveEditing()"&&/student&
完整例子:
&div ng-controller='demoCtrl'&
&!--指令scope.stu双向绑定demoCtrl scope.guy--&
&!--指令scope.onSave函数指向demoCtrl scope.saveEditing()--&
&student stu="guy" on-save="saveEditing()"&&/student&
&script type="text/html" id="t1"&
&div class="panel"&
&span&name:&/span&
&input type="text" ng-model="stu.name" /&
&span&sexy :&/span&
&select ng-model="stu.sexy"&
&option value="1"&male&/option&
&option value="2"&female&/option&
&button class="btn btn-info" type="button" ng-click="onSave()"&save&/button&
var app = angular.module("app", []);
app.controller('demoCtrl', function ($scope) {
$scope.guy = {
name: "mark",
$scope.saveEditing = function () {
//$http.post("...", { stu: $scope.guy });
console.log($scope.guy.name + " is saving!");
console.log($scope.guy);
app.directive('student', function () {
restrict: 'E',
//=为双向绑定策略
onSave: '&'
//$反向调用父域函数策略
template: function (elem, attr) {
return document.getElementById('t1').innerHTML;
controller: function ($scope, $element, $attrs, $transclude) {
//这里省略信息卡交互逻辑……
ngModel,这个内置指令相信大家都不会陌生。自定义指令引用其自身的ngModel指令,其原理就是:
父域对象 绑定 ngModel
ngModel 绑定 指令子域对象
优点:可以充分利用ngModel的特性,例如commit、rollback等特性,也可以搭配ng-model-options进行使用。
相对于方案1,父子对象绑定中间还要多一层ngModel的绑定,性能必然降低;
相对于方案1,使用比较麻烦;
自身不能实现反向调用父域函数,需要借助$parse转换表达式方案实现
&student ng-model="guy" on-save="saveEditing()"&&/student&
完整例子:
&div ng-controller='demoCtrl'&
&student ng-model="guy" on-save="saveEditing()"&&/student&
&script type="text/html" id="t1"&
&div class="panel"&
&span&name:&/span&
&input type="text" ng-model="ngModel.$modelValue.name" /&
&span&sexy :&/span&
&select ng-model="ngModel.$modelValue.sexy"&
&option value="1"&male&/option&
&option value="2"&female&/option&
&button class="btn btn-info" type="button" ng-click="onSave()"&save&/button&
var app = angular.module("app", []);
app.controller('demoCtrl', function ($scope) {
$scope.guy = {
name: "mark",
$scope.saveEditing = function () {
//$http.post("...", { stu: $scope.guy });
console.log($scope.guy.name + " is saving!");
console.log($scope.guy);
app.directive('student', ["$parse", function ($parse) {
restrict: 'E',
require: ['student', 'ngModel'],
scope: {},
template: function (elem, attr) {
return document.getElementById('t1').innerHTML;
link: function (scope, element, attr, ctrls) {
//link阶段,通过require获取指令自身的控制器,及ngModel指令的控制器
var stCtrl = ctrls[0];
var ngModelCtrl = ctrls[1];
//并将ngModel指令的控制器,通过自身控制器的init()方法传入到其中
stCtrl.init(ngModelCtrl);
controller: function ($scope, $element, $attrs, $transclude) {
//创建controller的对外初始化方法,并将外部ngModel的控制器设置本地作用域对象
this.init = function (ngModelCtrl) {
$scope.ngModel = ngModelC
//获得on-save属性指向的表达式{{saveEditing()}}
var saveInvoker = $parse($attrs.onSave);
$scope.onSave = function () {
//在父域中,执行表达式{{saveEditing()}}——执行父域saveEditing()
saveInvoker($scope.$parent, null);
在ngModel的解决方案中,已经有过通过$parse获取执行表达式操作父域函数的例子:$parse($attrs.onSave)。这个方案不仅能够执行父域函数表达式,同时也能够执行对象的get/set表达式。但是本方案本质其实是对于父域$scope.$parent的直接操作,只是通过$parse服务实现解耦。
关于$parse服务,想了解更多,请移步——
&div ng-controller='demoCtrl'&
&student stu="guy" on-save="saveEditing()"&&/student&
&script type="text/html" id="t1"&
&div class="panel"&
&span&name:&/span&
&input type="text" ng-model="stu.name" /&
&span&sexy :&/span&
&select ng-model="stu.sexy"&
&option value="1"&male&/option&
&option value="2"&female&/option&
&button class="btn btn-info" type="button" ng-click="onSave()"&save&/button&
var app = angular.module("app", []);
app.controller('demoCtrl', function ($scope) {
$scope.guy = {
name: "mark",
$scope.saveEditing = function () {
//$http.post("...", { stu: $scope.guy });
console.log($scope.guy.name + " is saving!");
console.log($scope.guy);
app.directive('student', ["$parse", function ($parse) {
restrict: 'E',
scope: {},
template: function (elem, attr) {
return document.getElementById('t1').innerHTML;
controller: function ($scope, $element, $attrs, $transclude) {
var getClassName,
setClassName,
saveInvoker = angular.
//注意:建议查阅一下$parse内置表达式转换函数的使用方法。
//获得stu属性指向的表达式{{guy}}
getStudent = $parse($attrs.stu);
setStudent = getStudent.
//获得on-save属性指向的表达式{{saveEditing()}}
saveInvoker = $parse($attrs.onSave);
//监听父域的{{guy}}
$scope.$parent.$watch(getStudent, function (stu) {
$scope.stu =
$scope.onSave = function () {
//在父域中,执行表达式{{guy}} assign——将本地对象stu设置到父域guy
setStudent($scope.$parent, $scope.stu);
//在父域中,执行表达式{{saveEditing()}}——执行父域saveEditing()
saveInvoker($scope.$parent, null);
说了一大堆,大家还是动手试试哪个方案更合适你的项目,或者有更好的开发思路。
下一章节,为大家介绍一下关于指令的自动化测试。欢迎继续捧场。
你可能感兴趣的文章
77 收藏,2.9k
2 收藏,1.6k
14 收藏,644
本作品采用 署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可
通信用事件发送的方式是否会好些!!!如果你的的父ctr没有那个变量,岂不是 这句话$scope.$parent.$watch就没有啥意义了吗?
第三弹什么时候出来?
感谢支持,下一弹想聊下karma驱动的单元测试,但发现很多坑,踩坑中
哈哈。现在在实习也是用angular.前2天leader说写单元测试,但是最近比较忙。就没有做这方面的工作。不过非常期待你的文章~~
单元测试还是很重要的,前端开发也应该像后端那样,以测试驱动作为开发思路。单元测试的话还好,karma+jasmine有不少好的实施方案,但是要做到端到端的测试就真的看水平了。哈哈
$emit、$broadcast做事件分发会比$watch做监听性能要好啊,但是不知道怎么解决指令与父控制器之间的耦合性问题。毕竟要用$on做接收
楼主,类似于点击按钮时弹出一个 div 层,这样的指令如何封装?我现在都是在html页面上写好了弹出层,ng-show="box.state",然后点击时修改 box.state,然后就弹出 div 层了。我想实现的功能类似于 alert,里面显示不同的文本内容。
楼主啥时候写你的自动化测试的内容呀?
106 收藏,
分享到微博?
技术专栏,帮你记录编程中的点滴,提升你对技术的理解收藏感兴趣的文章,丰富自己的知识库
明天提醒我
我要该,理由是:
扫扫下载 App
SegmentFault
一起探索更多未知

我要回帖

更多关于 angularjs 模块化 的文章

 

随机推荐