关于angularJS自定义指令属性:transclude、priority、terminal和angular自定义指令例子的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于angular指
关于angularJS 自定义指令 属性:transclude、priority、terminal和angular自定义指令例子的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于angular 指令之属性 transclude 和 scope、angular.js指令中transclude选项及ng-transclude指令详解、AngularJS - 自定义指令、AngularJS transclude不起作用等相关知识的信息别忘了在本站进行查找喔。
本文目录一览:- angularJS 自定义指令 属性:transclude、priority、terminal(angular自定义指令例子)
- angular 指令之属性 transclude 和 scope
- angular.js指令中transclude选项及ng-transclude指令详解
- AngularJS - 自定义指令
- AngularJS transclude不起作用
angularJS 自定义指令 属性:transclude、priority、terminal(angular自定义指令例子)
自定义指令的属性 transclude:为true时,允许把html中新定义的指令中原来的dom运用到该指令的template中。
属性priority,设置该指令的优先级,优先级大的先执行,默认指令的优先级是0(但ng-repeat指令的优先级默认是1000)。 属性terminal:为true时,指示优先级小于当前指令的指令都不执行,仅执行到本指令。
示例:
html:
<div ng-app="myApp"> <div ng-controller="firstController"> <h3>custom-tags 指令:</h3> <div custom-tags>原始数据</div> <h3>一个div上同时使用 custom-tags2 指令 和 custom-tags3 指令:</h3> <div custom-tags2 custom-tags3></div> </div> </div>js:
angular.module('myApp',[]) //定义第一个指令:customTags .directive('customTags',function(){ return { restrict:'ECAM',template:'<div>Hello <span ng-transclude></span> world!</div>',//<span ng-transclude></span> 原来的dom transclude:true,//为true时,允许把节点内原来的dom放入template中 replace:true //为true时,设置的template或templateUrl都必须仅由一个最外层标签包裹 } }) //定义第二个指令:customTags2 .directive('customTags2',template:'<div>222</div>',replace:true,priority:-1 //指示指令的优先级,优先级大的先执行,默认指令们的优先级都是0,但ng-repeat指令的优先级是1000 } }) //定义第三个指令:customTags3 .directive('customTags3',template:'<div>333</div>',priority:0,terminal:true //为true时,指示优先级小于本指令的优先级的directive都不再执行 } }) .controller('firstController',['$scope',function($scope){ }]);执行结果:
angular 指令之属性 transclude 和 scope
1、不继承父作用域的 scope 属性
<!-- 前端代码 -->
<div ng-controller="testCtrl">
<my-directive name="456"></directive>
</div>
/* 指令代码 */
return {
restrict: ''E'',
scope: {},
link: function(scope){
scope.name = ''123'';
},
templateUrl: ''模板.html''
};
directive 返回的对象中存在 scope 属性,说明 myDirective 的模板文件的作用域不继承父作用域 testCtrl 的,即使这是个空对象 ---scope: {}。
如果这里的 socpe 为:
scope: {
name: ''@''
}
那指令控制器域的 name 就不再是 123,而是被其指令标签属性上 name 覆盖,结果为 456。
2、transclude: true
/* JS代码 */
function testCtrl($scope){
$scope.name = "789";
}
/* 指令返回 */
return {
restrict: ''E'',
scope: {}, // 代码(2)的值为123
//transclude: true, 出现这个的话,代码(1)的值会被testCtrl里面的覆盖,即为789
//scope: {name: ''@''}, 这样的话代码(2)的值就会被标签属性上的覆盖,即为456
link: function(scope){
scope.name = ''123'';
},
templateUrl: ''模板.html''
};
<!-- 前端代码 -->
<div ng-controller="testCtrl">
<my-directive name="456">转置后的域,继承父控制器testCtrl的域(1): {{name}}</directive>
</div>
<!-- 模板代码 -->
<div ng-transclude>
</div>
处于指令控制器域(2):{{name}}
transclude 的出现,使得代码(1)处的作用域设为指令父控制器 testCtrl 的域,为 789。
但是如果没有 scope 属性的出现,代码(1)处的 name 将会被指令控制器域覆盖,name 的值为 123。
3、scope 的代理(映射)模式
/* JS代码 */
function testCtrl($scope){
$scope.textCtrlName = "789";
}
/* 指令返回 */
return {
restrict: ''E'',
scope: {
name: ''=''
},
link: function(scope){
scope.name = ''123'';//这里屏蔽掉的话name的值则为789
},
templateUrl: ''模板.html''
};
<!-- 前端代码 -->
<div ng-controller="testCtrl">
<my-directive name="textCtrlName"></directive>
</div>
<!-- 模板代码 -->
{{name}}
采用 scope 代理模式,优先级小于 link 函数的。
如果去掉 link 内的赋值,结果 name 为 789,否则为 123。
angular.js指令中transclude选项及ng-transclude指令详解
前言
在开始本文之前,首先要说明我们使用的angular的版本是1.5.0,因为不同版本的表现结果不是那么相同。
首先我们应该了解到,在angular指令的选项中,有一项是transclude,这个选项有三种值:false,true,object;那这三种值分别表示什么,该如何选择?
下面我们来详细的说明一下。
transclude字面意思就是嵌入,也就是说你需不需要将你的指令内部的元素(注意不是指令的模板)嵌入到你的模板中去,默认是false。如果你需要这种功能的话,那么就需要将transclude设置为true或者{...}。如果将这个值设置为true或者{...}的话,那么就要配合angular的ng-transclude指令来进行使用,好,废话不多说了,看代码是最好的学习方法,我们下面就来根据代码来了解掌握这些东西。
代码的结果可以在nofollow" target="_blank" href="http://angularjs.leanapp.cn/article/ng-transclude/">这里看到,完整的代码会在后面贴出来。
现在我们来看第一个指令部分
1、在页面中使用的形式
AngularJS - 自定义指令
这一篇从自定义指令出发,记录了定义一个指令时影响指令行为的各种因素。
试着感受这些因素,让自己更高效地编写AngularJS应用。
Directive
先从定义一个简单的指令开始。
定义一个指令本质上是在HTML中通过元素、属性、类或注释来添加功能。
AngularJS的内置指令都是以ng
开头,如果想自定义指令,建议自定义一个前缀代表自己的命名空间。
这里我们先使用my
作为前缀:
var myApp = angular.module(''myApp'', [])
.directive(''myDirective'', function() {
return {
restrict: ''A'',
replace: true,
template: ''<p>Kavlez</p>''
};
})
如此一来,我们可以这样使用,注意命名是camel-case:
<my-directive />
<!-- <my-directive><p>Kavlez</p></my-directive> -->
directive()
接受两个参数
- name:字符串,指令的名字
- factory_function:函数,指令的行为
应用启动时,以name作为该应用的标识注册factory_function返回的对象。
在factory_function中,我们可以设置一些选项来改变指令的行为。
下面记录一下定义指令时用到的选项
restrict (string)
该属性用于定义指令以什么形式被使用,这是一个可选参数,本文开头定义的指令用的也是A,其实该选项默认为A。
也就是元素(E)、属性(A)、类(C)、注释(M)
(ps:EMAC? EMACS? 挺好记哈)
比如上面定义的myDirective
,可以以任何形式调用。
- E(元素)
<my-directive></my-directive>
- A(属性,默认值)
<div my-directive="expression"></div>
- C(类名)
<div></div>
- M(注释)
<--directive:my-directive expression-->
priority (Number)
也就是优先级,默认为0。
在同一元素上声明了多个指令时,根据优先级决定哪个先被调用。
如果priority相同,则按声明顺序调用。
另外,no-repeat
是所有内置指令中优先级最高的。
terminal (Boolean)
终端? 而且还是Boolean?
被名字吓到了,其实terminal的意思是是否停止当前元素上比该指令优先级低的指令。
但是相同的优先级还是会执行。
比如,我们在my-directive
的基础上再加一个指令:
.directive(''momDirective'',function($rootScope){
return{
priority:3,
terminal:true
};
})
调用发现my-directive
不会生效:
<div mom-directive my-directive="content" ></div>
template (String/Function)
至少得输出点什么吧? 但template也是可选的。
String类型时,template可以是一段HTML。
Function类型时,template是一个接受两个参数的函数,分别为:
- tElement
- tAttrs
函数返回一段字符串作为模板。
templateUrl (String/Function)
这个就和上面的template很像了,只不过这次是通过URL请求一个模板。
String类型时,templateURL自然是一个URL。
Function类型时返回一段字符串作为模板URL。
replace (Boolean/String)
默认值为false,以文章开头定义的指令为例,假设我们这样调用了指令
<my-directive></my-directive>
replace为true时,输出:
<p>Kavlez</p>
replace为false时,输出:
<my-directive><p>Kavlez</p></my-directive>
transclude (Boolean)
该选项默认为false,翻译过来叫''嵌入'',感觉还是有些生涩。
template
和scope
已经可以做很多事情了,但有一点不足。
比如在原有元素的基础上添加内容,transclude
的例子如下:
<body ng-app="myApp">
<textarea ng-model="content"></textarea>
<div my-directive title="Kavlez">
<hr>
{{content}}
</div>
</body>
<script type="text/javascript">
var myApp = angular.module(''myApp'', [])
.directive(''myDirective'', function() {
return {
restrict: ''EA'',
scope: {
title: ''@'',
content: ''=''
},
transclude: true,
template: ''<h2>{{ title }}</h2>\
<spanng-transclude></span>''
};
});
</script>
发现div下的hr并没有被移除,就是这样的效果。
注意不要忘了在模板中声明ng-transclude
。
scope (Boolean/Object)
默认为false,true时会从父作用域继承并创建一个自己的作用域。
而ng-controller
的作用也是从父作用域继承并创建一个新的作用域。
比如这样,离开了自己的作用域就被打回原形了:
<div ng-init="content=''from root''">
{{content}}
<div ng-controller="AncestorController">
{{content}}
<div ng-controller="ChildController">
{{content}}
</div>
{{content}}
</div>
{{content}}
</div>
.controller(''ChildController'', function($scope) {
$scope.content = ''from child'';
})
.controller(''AncestorController'', function($scope) {
$scope.content = ''from ancestor'';
})
但不要误解,指令嵌套并不一定会改变它的作用域。
既然true
时会从父作用域继承并创建一个自己的作用域,那么我们来试试改为false
会是什么样子:
<div ng-init="myProperty=''test''">
{{ myProperty }}
<div my-directive ng-init="myProperty = ''by my-directive''">
{{ myProperty }}
</div>
{{ myProperty }}
</div>
.directive(''myDirective'', function($rootScope) {
return {
scope:false
};
})
显然,结果是三行''by my-directive''。
非true即false? naive!
其实最麻烦的还是隔离作用域,
我们稍微改动一下myDirective,改为输出<p>{{内容}}</p>
。
于是我试着这样定义:
<body ng-app="myApp" >
<p ng-controller="myController">
<div my-directive="I have to leave." ></div>
{{myDirective}}
</p>
</body>
<script type="text/javascript">
var myApp = angular.module(''myApp'', [])
.directive(''myDirective'', function($rootScope) {
$rootScope.myDirective = ''from rootScope'';
return {
priority:1000,
restrict: ''A'',
replace: true,
scope: {
myDirective: ''@'',
},
template: ''<p>{{myDirective}}</p>''
};
})
.controller(''myController'',function($scope){
$scope.myDirective = ''from controller'';
});
</script>
这里需要注意的不是@
,重点是隔离作用域。
根据上面的例子输出,template中的{{myDirective}}
不会影响到其他作用域。
我们再试试这样:
<input type="text" ng-model="content">
<p ng-controller="myController" >
<div my-directive="{{content}}" ></div>
{{content}}
</p>
发现大家都在一起变,也就是说值是通过复制DOM属性并传递到隔离作用域。
ng-model
是个强大的指令,它将自己的隔离作用域和DOM作用域连在一起,这样就是一个双向数据绑定。
如何向指令的隔离作用域中传递数据,这里用了@
。
或者也可以写成@myDirective
,也就是说换个名字什么的也可以,比如我用@myCafe
什么的给myDirective赋值也是没问题的,总之是和DOM属性进行绑定。
另外,我们也可以用=
进行双向绑定,将本地作用域的属性同父级作用域的属性进行双向绑定。
比如下面的例子中,隔离作用域里的内容只能是''abc'' :
<body ng-app="myApp" ng-init="content=''abc''">
<p ng-controller="myController" >
<input type="text" ng-model="content">
<div my-directive="content" ></div>
{{content}}
</p>
</body>
<script type="text/javascript">
var myApp = angular.module(''myApp'', [])
.directive(''myDirective'', function($rootScope) {
return {
priority:1000,
restrict: ''A'',
replace: true,
scope: {
myDirective: ''='',
},
template: ''<p>from myDirective:{{myDirective}}</p>''
};
})
.controller(''myController'',function($scope){
$scope.content = ''from controller'';
});
</script>
在隔离作用域访问指令外部的作用域的方法还有一种,就是&
。
我们可以使用&
与父级作用域的函数进行绑定,比如下面的例子:
<body ng-app="myApp">
<div ng-controller="myController">
<table border=''1''>
<tr>
<td>From</td>
<td><input type="text" ng-model="from"/></td>
</tr>
<tr>
<td>To</td>
<td><input type="text" ng-model="to"/></td>
</tr>
<tr>
<td>Content</td>
<td><textarea cols="30" rows="10" ng-model="content"></textarea></td>
</tr>
<tr>
<td>Preview:</td>
<td><div scope-example to="to" on-send="sendMail(content)" from="from" /></td>
</tr>
</table>
</div>
</div>
</body>
<script type="text/javascript">
var myApp = angular.module(''myApp'', [])
.controller(''myController'',function($scope){
$scope.sendMail=function(content){
console.log(''content is:::''+content);
}
})
.directive(''scopeExample'',function(){
return{
restrict:''EA'',
scope: {
to: ''='',
from: ''='' ,
send: ''&onSend''
},
template:''<div>From:{{from}}<br>\
To:{{to}}<br>\
<button ng-click="send()">Send</button>\
</div>''
}
})
</script>
controller (String/Function)
控制器也可以在指令里定义,比如:
.directive(''myDirective'', function() {
restrict: ''A'',
controller: ''myController''
}).controller(''myController'', function($scope, $element, $attrs,$transclude) {
//...
})
相同的效果,也可以这样声明:
directive(''myDirective'', function() {
restrict: ''A'',
controller:function($scope, $element, $attrs, $transclude) {
//...
}
});
controllerAs (String)
可以从名字和类型看出,这个选项是用来设置控制器的别名的。
比如这样:
directive(''myDirective'', function() {
restrict: ''A'',
controller:function($scope, $element, $attrs, $transclude) {
//...
}
});
compile (Object/Function)
虽说这个东西不是很常用吧,但却是值得了解的选项。
compile
和link
,这两个选项关系到AngularJS的生命周期。
先在这里简单记录一下我对生命周期的认识。
- 应用启动前,所有的指令以文本的形式存在。* 应用启动后便开始进行compile和link,DOM开始变化,作用域与HTML进行绑定。* 在编译阶段,AngularJS会遍历整个HTML并处理已声明的指令。
- 一个指令的模板中可能使用了另外一个指令,这个指令的模板中可能包含其他指令,如此层层下来便是一个模板树。* 在DOM尚未进行数据绑定时对DOM进行操作开销相对较小,这时像
ng-repeat
之类的指令对DOM进行操作则再合适不过了。 - 我们可以用编译函数访问编译后的DOM,在数据绑定之前用编译函数对模板DOM进行转换,编译函数会返回模板函数。
也就是说,设置compile函数的意义在于:在指令和实时数据被放到DOM中之前修改DOM。
此时完全可以毫无顾虑地操作DOM。 - 接着我们便可以进入下一个阶段,链接阶段。
- 最后,模板函数传递给指令指定的链接函数,链接函数对作用域和DOM进行链接。
好了,接下来我们就试试compile:
<body ng-app="myApp">
<my-directive ng-model="myName"></my-directive>
</body>
<script type="text/javascript">
var myApp = angular.module(''myApp'', [])
.directive(''myDirective'', function($rootScope) {
$rootScope.myName = ''Kavlez'';
return {
restrict: ''EA'',
compile:function(tEle, tAttrs, transcludeFn) {
var h2 = angular.element(''<h2></h2>'');
h2.attr(''type'', tAttrs.type);
h2.attr(''ng-model'', tAttrs.ngModel);
h2.html("hello {{"+tAttrs.ngModel+"}}");
tEle.replaceWith(h2);
}
};
});
</script>
原文出处 AngularJS - 自定义指令
AngularJS transclude不起作用
https://egghead.io/lessons/angularjs-transclusion-basics
app.directive("panel",function() { return { restrict: "E",transclude: true,template: '<divng-transclude>This is a panel component</div>' } })
AngularJS 1.1.5:http://plnkr.co/edit/BLe56D9YZxSIAiJ31wW0(“这是……”按预期显示)AngularJS 1.2.5:http://plnkr.co/edit/h6dUrXXXBOQUtzsJqT4S(“这是……”没有出现)
在1.1.5“transclude:true”按预期工作(文本附加到面板),但在> 1.2.0没有.
有帮助吗?
解决方法
template: '<div>This is a panel component</div><div ng-transclude></div>'
今天关于angularJS 自定义指令 属性:transclude、priority、terminal和angular自定义指令例子的分享就到这里,希望大家有所收获,若想了解更多关于angular 指令之属性 transclude 和 scope、angular.js指令中transclude选项及ng-transclude指令详解、AngularJS - 自定义指令、AngularJS transclude不起作用等相关知识,可以在本站进行查询。
本文标签: