Angular 2 自定义 HTML 标签有多"safe"?(选择器:自定义标记与自定义属性)



这是一个关于Angular 2选择器、自定义标签与自定义属性、SEO和浏览器渲染的问题。

当我第一次开始查看Angular 2时,在跟踪他们的快速启动时,我做的第一件事就是将选择器更改为'[my-component]'(属性选择器)而不是'my-component'(标记选择器),这样我就可以在HTML中使用<div my-component></div>而不是<my-component></my-component>,这是无效的HTML。所以我会按照标准编写HTML。好吧,至少相当接近标准(因为my-component不是一个有效的HTML属性,但我只能忍受HTML验证错误)

然后,在YouTube上的一段视频中,angular团队的某个人提到,我们应该使用标签选择器,至少在性能方面是这样。

好吧,我说,该死的HTML验证。。。还是我不应该
因此:

  1. 假设我忽略W3C对我的HTML由于<custom-tags>而完全无效的尖叫。事实上,我还有另一个更大、更真实的担忧:这对SEO有何影响
    我的意思是,不要只考虑客户端应用程序,因为在现实世界中(对于我的angular 2项目也是如此),我也有服务器端渲染,这有两个非常重要的原因:SEO在应用程序启动之前,为用户提供网站的快速初始渲染。否则你不可能有一个流量很高的SPA
    当然,无论我使用什么标签,谷歌都会抓取我的网站,但在两种情况下,它的排名是否相同:一种是<custom-make-believe-tags>,另一种只有标准HTML标签?

  2. 让我们谈谈浏览器和CSS

当我开始在Angular 2中构建我的第一个SPA站点时,我立即面临另一个问题:
假设(在非SPA站点中)我有以下HTML标记:

<header>
<a class="logo">
...
</a>
<div class="widgets">
<form class="frm-quicksearch"> ... </form>
<div class="dropdown">
<!-- a user dropdown menu here -->
</div>
</div>
</header>
<div class="video-listing">
<div class="video-item"> ... </div>
<div class="video-item"> ... </div>
...
</div>

角度2方面,我会有以下组件树:

<header-component>
<logo-component></logo-component>
<widgets-component>
<quicksearch-component></quicksearch-component>
<dropdown-component></dropdown-component>
</widgets-component>
</header-component>
<video-listing-component>
<video-item-component></video-item-component>
...
</video-listing-component>

现在,我有两个选择。让我们以<video-listing-component>为例,保持简单。。。我要么
A)将我已经拥有的整个标准HTML标记(<div class="video-item"></div>)放置在<video-item-component>标记中,一旦渲染,将产生以下结果:

<video-listing-component>
<div class="video-listing>
<video-item-component>
<div class="video-item>...</div>
</video-item-component>
...
...
</div>
</video-listing-component>

B)只将<div class="video-item">的内容直接放入我的<video-item-component>组件中,并在组件标签上添加所需的类(class="video-item")以进行样式设置,结果如下:

<video-listing-component class="video-listing">
<video-item-component class="video-item"></video-item-component>
<video-item-component class="video-item"></video-item-component>
...
</video-listing-component>

无论哪种方式(AB),浏览器都会将一切渲染得很好
但是,如果仔细观察(当然,在DOM中呈现所有内容之后),默认情况下,自定义标记不会占用DOM中的任何空间。它们是0px乘0px。只有它们的内容占据了空间。我不明白为什么浏览器仍然按照你想要的方式呈现所有内容,我的意思是在第一种情况下(A):

虽然div class="video-item"上有float: left; width: 25%;,但这些div中的每一个都一个<video-item-component>标签中,该标签没有任何样式。。。浏览器按照您的期望呈现所有内容,这难道不是一个幸运的副作用吗?所有的<div class="video-item">相邻浮动,即使它们都在另一个标签内,没有浮动的<video-item-component>:左?我已经在IE10+、Firefox、Chrome上进行了测试,一切都很好。这是幸运的吗?还是对此有一个可靠的解释,我们可以放心地相信,所有(或至少大多数)浏览器都会像我们所期望的那样呈现这种标记?

第二种情况(B):

如果我们直接在自定义标记(<video-item-component>)上使用类和样式。。。再说一遍,一切都很好。但据我所知,我们不应该设计自定义组件的样式,对吧?这不也是一个幸运的预期结果吗?或者这也可以吗?我不知道,也许我还活在2009年…是吗
这两种方法(AB)中的哪一种是推荐的方法?还是两者都很好?

我不知道

由于我的div有float:left,这就是为什么它们所封装的(自定义或非自定义)标签不会扩展它的高度。自从我开始研究Angular 2以来,我似乎已经忘记了CSS是如何工作的。

但有一件事仍然存在:

如果我在块元素上设置一个百分比宽度(称为E),我会假设它占用直接父元素的x%。如果我设置float:left,我希望在直接父级中浮动。在A的情况下,由于直接父标记是一个没有显示类型和宽度的自定义标记,我希望事情会以某种方式中断,但仍然。。。我的E元素的行为就像它们的父元素不是它们各自封装的自定义标记,而是DOM中的下一个标记(在我的例子中是<div class="video-listing>)。它们占据了其中的x%,并在其中浮动。我不认为这是正常的,我认为这只是一个幸运的效果,我担心有一天,在浏览器更新后。。。我醒来后会发现我所有的Angular 2网站看起来都完全崩溃了。

所以。。。AB都是同样合适的方法吗?还是在A的情况下我做错了?

EDIT2
让我们稍微简化一下。当我得到部分问题的答案时,让我们举另一个生成HTML的例子(简化了一点,使用内联CSS):

<footer>
<angular-component-left>
<div style="float: left; width: 50%;">
DIV CONTENT
</div>
</angular-component-left>
<angular-component-right>
<div style="float: left; width: 50%;">
DIV CONTENT
</div>
</angular-component-right>
</footer>

在最初尚未实现的HTML中(如果没有<angular-component-...>,这些div应该向左浮动,每个div占据<footer>的50%。令人惊讶的是,一旦它们被<angular-component-...>自定义标签包裹起来,它们也会做同样的事情:占据页脚的50%。但这对我来说似乎是好运,愚蠢的运气…意外的效果。
那么,这是"愚蠢的运气"吗?

如果我这样写,或者重写,而不是上面的代码,我会有这样的东西:

<footer>
<angular-component-left style="display: block; float: left; width: 50%;">
DIV CONTENT
</angular-component-left>
<angular-component-right style="display: block; float: left; width: 50%;">
DIV CONTENT
</angular-component-right>
</footer>

注意,为了简单起见,这里引入了内联样式,实际上我会有一个类,它将位于文档的<head>中包含的外部CSS文件中,而不是通过角度组件的stylestyleUrls

问题在于HTML验证器。元素名称中的-是被视为自定义元素的元素所必需的,并且它是有效的HTML5。Angular在元素名称中不需要-,但这是一种很好的做法。

例如检查https://www.w3.org/TR/custom-elements/#registering-自定义元素(搜索x-foo)或https://w3c.github.io/webcomponents/spec/custom/#custom-元素自定义标记示例。我确信这个破折号规则是在某个地方指定的,但找不到规范。例如,它在Polymer中是必需的,这取决于元素是正确的自定义元素,而在Angular中这并不重要。据我所知,唯一的区别是,当您查询元素时,当名称中缺少-时,您会得到HTMLUnknownElement,而当名称中包含-时,您将得到HTMLElement

另请参阅我几年前问的这个问题:为什么Angular在组件名称中不需要破折号

但如果仔细观察,默认情况下,自定义标记不会占用dom中的任何空间。它们是0px乘0px。只有它们的内容占据了空间。我只是不明白为什么浏览器仍然渲染所有你想看到的

我不确定我是否理解这个问题。Angular处理模板时会动态添加内容。当您在浏览器中看到内容时,它在DOM中也可用,并且具有实际的维度。

搜索引擎爬网程序能够处理由JavaScript生成的页面。如果这还不够,服务器端呈现的页面可以向包含整个视图的爬网程序提供静态HTML。

最新更新