【问题标题】:Is it bad practice to use custom elements in HTML5? [duplicate]在 HTML5 中使用自定义元素是不好的做法吗? [复制]
【发布时间】:2013-08-13 04:51:55
【问题描述】:

使用document.getElementByTagName 之类的东西,您实际上可以创建自己的元素。

<arial>Hello</arial>

然后在 JS..

var a = document.getElementsByTagName("arial");

for(i = 0; i < a.length; ++i)
     a[i].style.fontFamily = "Arial"

我们有一个自定义元素,很简单。

我的问题归结为,这是不好的做法吗?有什么我没有注意到的缺点吗?

【问题讨论】:

  • 您不会在这里创建任何新的“自己的”元素,您只需将一些 css 应用于块节点元素。
  • Sebas:我知道,但这适用于存在真正功能差异的更高级的情况
  • 我曾经读过一篇博客,其中讨论了一些旧代码。一个(当时)自定义属性被添加到一堆元素中。该属性的名称是语言.....FastFwd 到 HTML5 和整个页面(和站点)中断 - 壮观。不幸的是,language 属性现在是标准的一部分,并导致浏览器表现出新的和不需要的行为。记住这一点,我建议您最好先创建已经存在的元素(即在 html5 规范中定义),然后再为它们提供唯一的 ID 或 CLASS 和/或提供使用 css 定位的能力。

标签: javascript html


【解决方案1】:

通常,您希望使用标准的 html 元素并使用它们的 ID 或类来定位它们。它将生成更清洁和可用的代码。

【讨论】:

    【解决方案2】:

    这样做的主要缺点是它在语义上无效。但是,浏览器会将其解析为块元素,直到您为其添加更多样式为止。

    不要制作自己的标签,而是使用class,也许还有data 属性来为你的DOM添加适当的属性。

    【讨论】:

    • data- 属性可以处理很多不同的用例。
    • 块元素到底有什么问题(我不擅长 HTML 而不是 JS)?
    • 没有问题 :) 我只是说浏览器会将任何它不知道它是什么的元素解释为块元素,而不是说,一个内联元素。
    • 对,使用自定义元素没有技术问题(现在,请参阅关于language attr 的评论以获取寓言)。但是不要大声说出来,因为有一个实际的理由来避免它们:不值得争论,唯一关心的是不喜欢它们的人。跨度>
    • 你部分不正确,@Bartek。并非所有浏览器都将未知元素呈现为块。 IE,例如,needs to have them specified as so。通过尝试创建自己的元素,再次显示您打开了多少蠕虫。
    【解决方案3】:

    我不会说这是不好的做法,但它几乎在任何情况下都过大了,它会使您的 HTML 标记根据W3 Validator 无效。你可以做的是给你的元素一个class,然后在JavaScript中使用getElementByClass引用它:

    // Grabs the first element with said class
    var foo = document.getElementsByClassName()[0];
    

    【讨论】:

      【解决方案4】:

      The W3C says you should not. 这是不好的做法。

      作者不得使用以下元素、属性或属性值 本规范或其他适用的不允许 规范,因为这样做会使 将来要扩展的语言。

      此外,HTML5 不是 XML。您应该只使用官方规范中列出的元素。

      【讨论】:

      • 我理解为什么 W3C 会反对它,但我正在考虑更实际的问题(你知道,搜索引擎或浏览器不呈现或类似的东西)
      • 如果您开始使用无效代码,您总是会冒着对搜索引擎索引您网站的方式产生负面影响的风险。此外,创建新元素需要大量开销,尤其是当您需要让您的网站跨新旧浏览器工作时。最后,如果您稍后创建的元素被添加到规范中,或者浏览器开始寻找与您想出的名称相同的元素,则可能会产生负面影响。简而言之,不要这样做。添加描述性ids 和classes。
      • @bobbybee 给你一个实际的例子,look at all these people crying and having a huge sense of entitlement 当他们依赖一些他们不应该拥有但十年来似乎工作得很好的东西时。也许他们不知道风险,但现在你知道了。
      • @bobbybee 再次阅读我关于属性的回答。 “作者不得使用本规范不允许的元素、属性或属性值……”
      • @MichaelIrigoyen 虽然请注意 HTML5 确实 允许以“data-”为前缀的自定义属性 - 请参阅 html5doctor.com/html5-custom-data-attributes(这在许多库中使用,比如我第一次看到的 Lightbox 2)
      【解决方案5】:

      前向兼容性

      正如 cmets 中所述,创建这样的元素是不安全的。例如,假设输入元素不存在,但后来创建。

      <input>Some Content</input>
      

      浏览器将其重写为(为清楚起见,XHTML):

      <input />Some Content
      

      SEO 和可访问性

      HTML5 页面提供了描述内容的元素。这有助于搜索引擎了解您的页面。如果他们不理解您的页面,可能会降低您的排名。

      如果您坚持使用这些标签,并且将它们用于不止一个文本块,您应该给它们rolesaria-tags。这有助于搜索引擎和需要屏幕阅读器或其他无障碍服务的人。

      样式性

      在您以编程方式创建元素之前,某些浏览器不会让 CSS 样式生效。 html5shiv 使用相同的技术让旧浏览器支持新的 HTML5 元素。

      document.createElement("arial"); // don't need to do anything with it
      

      替代浏览器:data-*

      demo

      您可以使用data-something 属性来标记元素以进行替换。例如:

      <span data-large>Large Text</span>
      

      然后,您可以使用重写器将它们替换为不同的 HTML。本示例使用 jQuery 和一种极其简单的模板语言。

      rewrites = {
          large: '<span style="font-size: 2em">{}</span>'
      };
      
      function rewrite(r) {
          for (rule in r) {
              // build a selector in the form of [data-something]
              var selector = "[data-{}]".replace("{}", rule)
              $(selector).each(function (i, el) {
      
                  // get our inner html and inject it into our template
                  var inner = $(this).html();
                  var templated = r[rule].replace("{}", inner);
      
                  // replace the element with our new HTML
                  $(this).replaceWith(templated);            
      
              });
          }
      }
      
      rewrite(rewrites);
      

      服务器端/构建

      您可以使用您喜欢的任何标签编写代码,但在它到达您的浏览器之前在服务器上对其进行转换。这是一个用 jQuery(客户端)编写的 demo,但与 Cheerio(nodejs)兼容。

      rewrites = {
          large: '<span style="font-size: 2em">{}</span>'
      };
      
      function rewrite($, r) {
          for (rule in r) {
              $(rule).each(function (i, el) {
                  var inner = $(this).html();
                  var templated = r[rule].replace("{}", inner);
                  $(this).replaceWith(templated);            
              });
          }
      }
      
      rewrite($, rules)
      

      这既可以作为构建脚本,也可以作为一个非常简单的服务器端模板。这样,浏览器和搜索引擎就永远不会看到我们组成的元素。如果您需要这些虚拟元素,我推荐此解决方案。

      【讨论】:

      • 在 AngularJS 中使用自定义标签没有什么不同,如果将来新的语义附加到当前无意义的自定义元素上,它可能会产生未知的副作用,而不管 AngularJS。
      • 不正确。您可以替换整个元素,因此除非新浏览器添加拒绝 DOM api 的元素,否则这不会成为问题。我会添加一个更好的选择。
      • 但该元素仍在html中,并在任何角度生效之前进行解析。假设您的元素名称是&lt;cloak&gt;&lt;shadow&gt;,将来这意味着它下面的任何元素都会变成shadow dom 或其他任何东西。然后,它的角度代码会中断。只是一个例子。
      • 好点。我添加了一个服务器端替代方案。如果您担心 HTML 的变化,请不要在未确保不会破坏任何内容的情况下升级您的解析器。
      • @Esailija,我更新了我的答案。你有什么进一步的意见吗?
      猜你喜欢
      • 2015-07-02
      • 2012-04-08
      • 2011-02-18
      • 2012-08-06
      • 1970-01-01
      • 1970-01-01
      • 2011-12-02
      相关资源
      最近更新 更多