undertow_DOM的Undertow

undertow

UPDATE 2015.03.17: The accessibility concerns I expressed in this article are incorrect, and were based on misunderstanding. In fact, there are no such accessibility issues with Shadow DOM and screenreaders

更新2015.03.17:我在本文中表达的可访问性问题是错误的,并且是基于误解。 实际上,Shadow DOM和屏幕阅读器不存在此类可访问性问题



Shadow DOM is part of the Web Components specification, and is designed to address the encapsulation problems that plague some kinds of web development.

Shadow DOMWeb组件规范的一部分,旨在解决困扰某些Web开发的封装问题。

You know the kind of thing — if you build a custom widget, how do you avoid naming conflicts with other content on the same page? Most significantly, how do you prevent the page’s CSS from affecting your widget?

您知道这种事情–如果您构建自定义窗口小部件,如何避免与同一页面上其他内容的命名冲突? 最重要的是, 如何防止页面的CSS影响小部件?

It’s easy if you control the whole page, but that’s often not the case — not if you’re making widgets for other people to use. The problem there is that you have no idea what other CSS will be present. You can certainly reduce the likelihood of such problems, by defining all your selectors as descendants from something with high specificity:

如果您控制整个页面很容易,但是通常不是这样-如果您要制作供其他人使用的小部件,则不然。 那里的问题是您不知道会出现什么其他CSS 。 通过将所有选择器都定义为具有高度特异性的事物的后代,您当然可以减少发生此类问题的可能性:

#mywidget > .mywidget-container
{
}
#mywidget > .mywidget-container > .mywidget-inner
{
}

But that’s only effective until the site defines a rule with two ID selectors. Or maybe you could use two, but then three come along!

但这只有在站点定义带有两个 ID选择器的规则后才有效。 也许您可以使用两个,但随后三个会出现!

Recently, I’ve been toying with the idea of defining dynamic selectors — the widget script traverses up the DOM and makes a note of every element ID between itself and the document root, then compiles selectors that include all those IDs.

最近,我一直在尝试定义动态选择器的想法-小部件脚本遍历DOM并记下其自身与文档根目录之间的每个元素ID,然后编译包括所有这些ID的选择器。

But even that’s not guaranteed. There’s really nothing we can do to entirely prevent this problem, except to use an <iframe>, but that’s not a good solution — iframes limit the size and shape of the widget, they make an additional server request, and they create a keyboard trap in some browsers (e.g. Opera 12, in which you can’t Tab out of an iframe once you’ve Tabbed into it). So for all those reasons, iframes are best avoided.

但这还不能保证。 除了使用<iframe>之外,我们真的无法采取任何措施完全避免此问题,但这不是一个好的解决方案-iframe会限制小部件的大小和形状,它们会发出其他服务器请求,并会创建键盘陷阱在某些浏览器中(例如Opera 12,在将其中的Tab键跳入iframe后,您无法将其跳出iframe)。 因此,出于所有这些原因,最好避免使用iframe。

进入阴影 (Into The Shadow)

The Shadow DOM aims to solve this issue. I won’t going into the details of how it works and how to use it (there are other articles that do that), but for the purposes of this article I’ll summarize it like this — the Shadow DOM encapsulates content by creating document fragments. Effectively, the content of a Shadow DOM is a different document, which is merged with the main document to create the overall rendered output.

Shadow DOM旨在解决此问题。 我不会详细介绍它的工作方式以及使用方法( 还有其他文章 ),但是出于本文的目的,我将这样总结:Shadow DOM通过创建文档来封装内容碎片 。 实际上,Shadow DOM的内容是一个不同的文档 ,该文档与主文档合并以创建整体呈现的输出。

In fact some browsers already use this to render some of their native widgets. If you open the Developer Tools in Chrome, select Show Shadow DOM from the settings panel (the cog icon bottom-right) and then inspect a "range" input, you’ll see something like this:

实际上,某些浏览器已经使用它来呈现其某些本机窗口小部件。 如果您在Chrome中打开开发者工具,请从设置面板中选择Show Shadow DOM (右下角的齿轮图标),然后检查"range"输入,您将看到类似以下内容:

<input type="range">
  #document-fragment
    <div>
      <div pseudo="-webkit-slider-runnable-track">
        <div></div>
      </div>
    </div>
</input>

But you can’t get to those elements through the DOM, because they’re hidden from it:

但是您无法通过DOM来访问那些元素,因为它们已被隐藏在其中:

alert(input.firstChild);		//alerts null

The shadow content is roughly analogous to an iframe document on a different domain — the DOM can see the iframe, but can’t see anything inside it.

影子内容大致类似于其他域上的iframe文档-DOM可以看到iframe,但看不到其中的任何内容。

So because it’s isolated, users can’t accidentally break it, there’s no possibility of naming conflicts with any classes or IDs you use, and the CSS on the main page won’t affect it at all.

因此,由于它是孤立的,用户不会意外破坏它,因此不可能与您使用的任何类或ID命名冲突,并且主页上的CSS完全不会影响它。

Sounds brilliant, doesn’t it?

听起来很棒,不是吗?

进入黑暗 (Into The Darkness)

But hang on … if all that content is not in the DOM, then doesn’t that mean it’s not exposed to accessibility APIs either?

但是请继续……如果所有这些内容都不在DOM中 ,那么这是否也就意味着它也不会暴露于可访问性API中?

Yes, that’s exactly what it means.

是的,这就是它的意思。

Anything you put in a Shadow DOM is inaccessible to browser-based access technologies, such as screenreaders. It’s not available to search-engines either, but that’s always the case with scripted content. However screenreaders are different — they are script-capable devices — and so they do have access to scripted content.

您放置在Shadow DOM中的任何内容都是基于浏览器的访问技术(例如screenreader)无法访问的 。 搜索引擎也不可用,但是脚本内容总是这样。 但是,屏幕阅读器是不同的-它们是具有脚本功能的设备-因此,它们确实可以访问脚本内容。

But not this content!

但这不是内容!

Of course the specification is not ignorant of this division. In essence, it assumes a distinction between elements that contain text-content or informational attributes, and those that are simply empty boxes to create visual parts, like the "range" input’s thumb. Let’s refer to these as content elements and utility elements.

当然,该规范并不忽略该划分。 从本质上讲,它假定包含文本内容或信息属性的元素与只是用于创建可视部分(例如"range"输入的拇指)的空框的元素之间存在区别。 让我们将它们称为content元素Utility元素

So how often do widgets have such a clear distinction between the two? For the "range" input example it’s obvious, but are all sliders built that way? I wrote a slider widget recently, for an accessible video player, and its markup looked like this:

那么小部件在多大程度上在两者之间有如此明显的区别? 对于"range"输入示例,这是显而易见的,但是所有滑块都以这种方式构建吗? 我最近为一个可访问的视频播放器编写了一个滑块小部件,其标记如下所示:

<label for="slider-thumb">
  <button type="button" id="slider-thumb" 
    role="slider" aria-orientation="horizontal"
    aria-valuemin="0" aria-valuemax="120" 
    aria-valuenow="75" aria-valuetext="Time: 01:15">
    <span></span>
  </button>
</label>

The only part of that slider which could be put inside a Shadow DOM, is the <span> inside the <button>. The <button> itself is important content, with ARIA attributes that provide dynamic information to screenreaders and other access technologies.

可以放在Shadow DOM内的滑块的唯一部分是<button>内的<button> <span> <button><button>本身是重要的内容,具有ARIA属性,可为屏幕阅读器和其他访问技术提供动态信息。

To make that work with Shadow DOM we’d have to move all the ARIA attributes to the outer <label>, give it tabindex, and then use Shadow DOM for the inner elements. But that would be less accessible because we’d lose native semantics (e.g. the label’s for attribute no longer makes a valid association), and it would be less useful because it means the widget can’t submit any form data (so we’d need a separate form control, such as a hidden input).

为了使它与Shadow DOM一起使用,我们必须将所有ARIA属性移动到外部<label> ,为其指定tabindex ,然后将Shadow DOM用于内部元素。 但这将难以访问,因为我们将失去本机语义(例如,标签的for属性不再建立有效的关联),并且它的用处也将减少,因为这意味着小部件无法提交任何表单数据(因此,需要单独的表单控件,例如隐藏的输入)。

But even if that were fine — and even if every widget we make has a clear and easy distinction between content and utility elements — the content part of the widget is still not encapsulated; it’s still vulnerable to naming-conflicts and unwanted CSS inheritance.

但是,即使这样很好-即使我们制作的每个小部件在内容和实用程序元素之间都有清晰且容易的区分- 小部件的内容部分仍未封装 ; 它仍然容易受到命名冲突和不必要的CSS继承的影响。

And we all know that some people won’t understand or respect that distinction anyway. People will use Shadow DOM for content, and use it to produce a whole new generation of inaccessible web applications.

我们都知道有些人无论如何也不会理解或尊重这种区别。 人们将使用Shadow DOM来获取内容,并使用它来生成新一代不可访问的Web应用程序。

I read a number of other articles about Shadow DOM in researching this one, and they all do the same thing — they all stop to make the point that you shouldn’t put content in a Shadow DOM, and then immediately afterwards they say, but let’s not worry about that.

我读了一些关于影子DOM的其他文章的研究这一块,他们都做同样的事情-他们都在不停地做,你不应该放在一个影子DOM内容,然后随即他们说了点, 但让我们不必担心

Brilliant! A whole group of users dismissed in one idle caveat!

辉煌! 一群用户在一个闲置的警告中被解雇了!

But let’s be kinder, hey. Let’s say that article examples can’t be judged in those terms. Let’s assume that everybody who uses Shadow DOM will do so with appropriate consideration, making sure they only use it for utility elements, not for content.

但是,让我们变得更加友善,嘿。 假设不能用这些术语来判断文章示例。 让我们假设使用Shadow DOM的每个人都会这样做,并确保他们仅将其用于实用程序元素,而不用于内容。

With that requirement, Shadow DOM only provides half a solution; and half a solution is no solution at all.

有了这个要求, Shadow DOM只提供了一半的解决方案 。 一半的解决方案根本不是解决方案。

进入光明 (Into The Light)

It seems to me that the entire concept of Shadow DOM is wrong. It’s an over-engineered approach that doesn’t really solve the problem, and any approach that uses document fragments will have the same flaw — as long as it’s necessary to differentiate between accessible and non-accessible elements.

在我看来,Shadow DOM的整个概念是错误的。 这是一种过度设计的方法,并不能真正解决问题, 任何使用文档片段的方法都将具有相同的缺陷,只要有必要区分可访问元素和不可访问元素。

What we really need is the conceptual opposite — a way of defining style-encapsulated subtrees which are still part of the document.

我们真正需要的是概念上的对立面-一种定义样式封装子树的方法, 这些子树仍然是文档的一部分

In other words, rather than having multiple documents that only the browser can traverse, we have a single document that only the browser treats as multiple documents.

换句话说,不是只有浏览器才能遍历多个文档,而是只有一个文件将浏览器视为多个文档。

This could be expressed with a simple element attribute:

这可以用一个简单的element属性表示:

<div encapsulated="encapsulated">

The HTML DOM would interpret that no differently — it’s just an element with a non-rendered attribute, same as any other. However the CSS DOM would interpret it as a kind of document fragment, effectively saying that the element and everything inside it does not inherit from higher scopes.

HTML DOM对此的解释没有什么不同-它只是一个具有未渲染属性的元素,与其他元素相同。 但是CSS DOM会将其解释为一种文档片段,有效地表示元素及其内部的所有内容都不会继承更高的范围

And we can already do the opposite — scoping styles to a subtree — either by using descendant selectors, or if you really must, using <style scoped> (although personally I’d avoid that until it’s available as a <link> attribute, because <style> elements undermine the separation of content and presentation).

而且我们已经可以做相反的工作-通过使用后代选择器,或者如果确实需要,可以使用<style scoped> (将<style scoped>到子树)(尽管我个人会避免使用它,直到它可以作为<link>属性使用,因为<style>元素破坏了内容和表示的分离。

To go with that encapsulated attribute, we could still use a better way to manage and template utility elements, but HTML is the wrong place to do that. Really, we shouldn’t have to define empty elements at all — they’re a functional necessity only because we have no other way of defining presentational subtrees — so that capability should be added to CSS.

要使用封装的属性,我们仍然可以使用更好的方法来管理和模板实用程序元素,但是HTML错误的选择 。 确实,我们根本不需要定义空元素-它们是功能上的必要性,仅仅是因为我们没有其他定义表示性子树的方式-因此应该将功能添加到CSS

In other words, it should be possible for a single element to define any number of pseudo-elements, and for pseudo-elements themselves to also define pseudo-elements. Something like this:

换句话说, 单个元素可以定义任意数量的伪元素 ,伪元素本身也可以定义伪元素。 像这样:

#mywidget::after
{
}
#mywidget::after + ::element
{
}
#mywidget::after > ::element
{
}
#mywidget::after > ::element + ::element
{
}

Which would create a virtual subtree like this:

它将创建一个虚拟子树,如下所示:

<div id="mywidget" encapsulated="encapsulated">
  Text content
  <after>
    <element></element>
    <element></element>
  </after>
  <element></element>
</div>

Defining that stuff in CSS would imply a clear and innate distinction, that no developer could fail to understand — content goes in HTML, presentation in CSS, just the way it should be.

CSS中定义这些内容将意味着清楚而与生俱来的区别,即没有开发人员会不明白-内容以HTML形式出现 ,以CSS形式出现 ,只是应该的样子。

It remains to be seen whether we’ll ever get anything like what I’m suggesting. But in the meantime, I can only urge you to remember the absolute distinction — don’t use Shadow DOM for anything except empty elements which convey no information. And if you want my best suggestion, don’t bother with it at all.

我们是否会得到我所建议的东西还有待观察。 但与此同时,我只能敦促您记住绝对的区别- 不要将Shadow DOM用于除了不传递任何信息的空元素以外任何东西 。 而且,如果您想要我的最佳建议,请不要理会。

翻译自: https://www.sitepoint.com/dark-shadow-dom/

undertow

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值