为什么角度区分`<my-element> </my-element>`和`<my-element>`?</my-element>

时间:2015-01-28 12:26:01

标签: javascript angularjs angularjs-directive

我刚刚发现了Angular 1.2.1的一个奇怪问题,在this fiddle中进行了演示(在IE,FF和Chrome中都进行了测试):如果我创建了一个非常简单的模板化指令,它就不能用作{{ 1}}如果它尚未首先用作<my-element />

这是来自小提琴的js代码:

<my-element></my-element>

和html:

angular.module('app', []);
angular.module('app').directive('myElement', function() {
    return {
        restrict: 'E',
        replace: true,
        template: '<p>Hello, element!</p>'
    };
});

我期望的输出是两段,内容为<div ng-app="app"> <my-element /> <my-element></my-element> </div> ,但我只得到一个。但是,如果我颠倒了两个Hello, element! - 标签的顺序,那么自动关闭标签就会出现,它们都会给出输出。

为什么Angular会以这种病态行为?

3 个答案:

答案 0 :(得分:3)

不应使用您自己的自闭标签

浏览器会解释标签是否为&#34;可自行关闭&#34;或不。

它并不知道你的标签是&#34;自我关闭&#34; (他只知道HTML标签),这就是为什么它有一种奇怪的行为。

www.w3.org上,您可以找到元素部分:

  

无效元素是一种元素,其内容模型绝不允许在任何情况下都具有内容

     

以下是HTML中完整的void元素列表:    area,base,br,col,command,embed,hr,img,input,keygen,link,meta,param,source,track,wbr

     

非void元素必须有一个结束标记,除非此引用的HTML元素部分中该元素的子部分表明其结束标记可以省略....

因此,结论是:不要在自己的标签上使用简短形式。

在浏览器中解释您自己关闭的标签

出现这种奇怪的行为是因为浏览器会解释一个自闭标记,就像所有兄弟姐妹的 之后

让我们暂时忽略AngularJS,让我们考虑3个不在HTML中的新标签:<x><y><z>。< / p>

E.g:

<x></x>
<y></y>
<z></z>

将显示在源代码中(Chrome中的 F12 )。

但是

<x></x>
<y/>
<z></z>

看起来像:

<x></x>
<y>
    <z></z>
</y>

现在,我们收到了这些信息,让我们回到AngularJS:

<my-element />
<my-element></my-element>

变为

<my-element>
    <my-element></my-element>
</my-element>

和&#34; main&#34; =找到父<my-element>,并由<p>Hello, element!</p>替换。 =&GT;一条输出线=&gt;在这种情况下,您还可以在第二行代码后面包含一些文本或其他标记,因为它们将包装在父代中,结果将是相同的。

但是,另一方面:

<my-element></my-element>
<my-element />

将成为

<my-element></my-element>
<my-element></my-element>

将显示2次。

答案 1 :(得分:2)

以下是问题: -

https://github.com/angular/angular.js/issues/1237

在HTML中没有自闭标签这样的东西。只有标签是叶子。叶片标签是固定的。

答案 2 :(得分:1)

作为对早期答案的补充,这将更好地了解发生的事情。在jsfiddle中运行它。

假设自闭标签是起始标签,所有后面的文字都被认为是指令的内容。

&#13;
&#13;
angular.module('app', []);
angular.module('app')
    .directive('myElement', function () {
    return {
        restrict: 'E',
        transclude: true,
        scope: {},
        template: '<p>Hello, <span ng-transclude></span> element!</p>'
    };
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
<div ng-app="app">
    <my-element/>
    <my-element>jfdsfkl</my-element>
    <my-element>jfdsfkl</my-element>
    
    <my-element/>    
    <my-element>jfdsfkl</my-element>    
</div>
&#13;
&#13;
&#13;