8

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

当我第一次开始查看 Angular 2 时,我按照他们的快速入门做的第一件事就是将我的选择器更改为'[my-component]'(属性选择器)而不是'my-component'(标签选择器),这样我就可以<div my-component></div>在我的 html而不是<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 标签,另一种是标准的 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>

Angular 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 x 0px。只有它们的内容占据空间。我不明白为什么浏览器仍然会呈现您希望看到的所有内容,我的意思是在第一种情况下(A):
虽然在float: left; width: 25%;div class="video-item",但每个 div 都一个<video-item-component>标签内,这不是有任何样式...浏览器呈现您所期望的一切不只是一个幸运的副作用吗?与所有<div class="video-item">漂浮在彼此旁边,即使它们每个都在另一个标签内,<video-item-component>哪个没有浮动:左?我已经在 IE10+、Firefox、Chrome 上测试过,一切正常。只是幸运还是对此有可靠的解释,我们可以安全地依赖所有(或至少大多数)浏览器所期望的这种标记来呈现?

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

我没意见!!

编辑
D'oh,谢谢 Günter Zöchbauer。是的,因为我的 div 有浮动:左,这就是为什么他们包裹的(自定义或非自定义)标签不会扩展它的高度。自从我开始查看 Angular 2 以来,似乎我已经忘记了 css 是如何工作的 :)
但有一件事仍然存在:
如果我在块元素上设置百分比宽度(称为 E),我会假设它需要 x% 是即时的父母。如果我设置浮动:左,我希望在直接父级内浮动。在我的 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 应该向左浮动,并且每个占据 50% 的<footer>空间。令人惊讶的是,一旦它们被包裹在<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来自我的角度组件。

4

1 回答 1

2

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

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

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

但是,如果您仔细观察,默认情况下自定义标签不会占用 dom 中的任何空间。它们是 0px x 0px。只有它们的内容占据空间。我只是不明白为什么浏览器仍然呈现您希望看到的所有内容

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

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

于 2016-05-15T15:51:37.983 回答