在本系列的第3篇文章中,我介绍了指令中定义的孤立作用域属性怎样传递参数给外部函数(初看起来需要一些技巧,一旦掌握要点就变得很简单了)。在这篇文章中,我将将继续介绍相关自定义指令的知识,主要介绍transclude和restrict这两个指令参数,看看它们有什么功能,以及怎样使用。
指令中的restrict
在HTML中,指令可以被定义为元素、属性、CSS类、注释。你怎样限定你的自定义指令使用方式呢?
可以使用restrict接口属性来规定自定义指令在HTML中怎么使用、在哪使用。这个接口属性的值有下边几种:
restrict的值 | 解释 |
---|---|
E | 当做元素使用。示例:<my-directive></my-directive> |
A | 当做元素属性使用。示例:<div my-directive="exp"></div> |
C | 当做元素上的样式类使用。示例:<div class="my-directive: exp;"></div> |
M | 当做注释使用(很少使用)。示例:<!-- directive: my-directive exp --> |
下边是一个指令用作元素或属性的例子。注意,这两个值之间没有被隔开。
app.directive('myDirectiveWithRestriction', function () {
return {
restrict: 'EA',
scope: {
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内部指令,它被用来决定在一个指令模板中哪个地方嵌入外部内容。下边的指令代码,使用这两个要点实现替换。
运行效果如下:
通过引用的方式包含文档或文档的一部分到另一个文档(见维基百科)。
如果你曾经加载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内部指令,它被用来决定在一个指令模板中哪个地方嵌入外部内容。下边的指令代码,使用这两个要点实现替换。
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body ng-app="directivesModule">
<hello>
<br/>
<span>原始的内容,</span><br/>
<span>还会在这里。</span>
</hello>
<hello>
</hello>
<script src="../../lib/angular.js"></script>
<script src="../../lib/jquery.js"></script>
<script>
var app = angular.module('directivesModule', []);
app.directive('hello', function() {
return {
restrict: 'E',
template: '<div>Hi there <span ng-transclude></span></div>',
transclude: true,
replace:false
};
});
</script>
</body>
</html>
运行效果如下:
Hi there
原始的内容,
还会在这里。
原始的内容,
还会在这里。
Hi there
在这个例子中,还可以看到有个replace属性,当这个属性设置为true时,将会使用模板替换掉页面中标签所在的DOM(示例中的hello标签);设置为false时,将会把模板放到标签内部。
在这个例子中,还可以看到有个replace属性,当这个属性设置为true时,将会使用模板替换掉页面中标签所在的DOM(示例中的hello标签);设置为false时,将会把模板放到标签内部。
总结
一旦你理解了transclude的使用方法,它将会变得很简单。就像视频中提到的,服务器端包含或者CSS样式单嵌入网页的概念与transclude类似。在指令中使用transclude 和ng-transclude,你可以使你的指令具有定制功能。
到这里,自定义指令系列是否结束了?不幸的是,没有结束。当指令模板中包含ng-repeat 或ng-if 时,transclude将会变得很复杂。我将会在接下来的文章中介绍如何处理这些场景。
原文地址:http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-4-transclusion-and-restriction