2

我正在为我们公司编写 RIA 系统(仅限 chrome)。不同控件的数量在增长,我决定使用 Shadow DOM 来简化代码。这很棒,但有时需要外部重新设计。这就是问题所在,例如:

任务栏:

<taskbar side="right">
  <menubtn />
  <applist scrollable>
    <btn app="SpoPlanMon" />
  </applist>
  <tray />
</taskbar>

使用 Shadow DOM,applist 转换为:

<applist>
  <scroll-wrap>
    <scroll-bar>
      <scroll-slider />
    </scroll-bar>
    <scroll-cont>
      <btn app="SpoPlanMon" />
    </scroll-cont>
  </scroll>
</applist>

在这种情况下,我需要<scroll-slider />根据<taskbar />边设置样式(在所谓的属性中指定,可以动态更改)。不幸的是,我不能只写taskbar[side="top"] scroll-slider {...},因为只允许下边界封装。

有没有办法从“另一边”选择元素?或者可能是类似的东西video::-webkit-media-controls-panel

4

2 回答 2

1

您可以使用 CSS 变量将左/右上下文传达给滑块。有关工作示例,请参阅此 jsfiddle 。(您必须在 Chrome中启用启用实验性 WebKit 功能标志。)

它是这样工作的:外部组件为依赖于上下文的每个属性设置一个变量(在这种情况下,位于左侧或右侧)。在这个例子中,我只是设置一个变量,一种颜色:

<style>
*[side="right"] {
  -webkit-var-slider-color: red;
}

*[side="left"] {
  -webkit-var-slider-color: green;
}
</style>
<taskbar side="right">
  <menubtn />
  <applist scrollable>
    <btn app="SpoPlanMon" />
  </applist>
</taskbar>​

该组件仅使用变量:

<applist>
  <style>
  scroll-slider {
    background: grey; /* default */
    background: -webkit-var(slider-color);
  }
  </style>
  <scroll-wrap>
    <scroll-bar>
      <scroll-slider />
    </scroll-bar>
    <scroll-cont>
      <btn app="SpoPlanMon" />
    </scroll-cont>
  </scroll>
</applist>

在此示例中,该<taskbar side="right">元素将滑块颜色变量设置为红色。CSS 变量会自动流入 Shadow DOM,因此在 applist 中,滚动滑块的背景设置为红色。如果您将任务栏更改为 side="left",则会重新计算样式,并且滚动滑块的背景会自动翻转为绿色。

如果要配置更多属性,只需使用更多变量即可。

在使用它的地方定义属性两次的目的

background: grey; /* default */
background: -webkit-var(slider-color);

就是处理没有设置变量的情况。在这种情况下,第二个属性定义将无效,导致它被删除,因此第一个属性定义适用。当变量设置正确时,第二个定义有效并覆盖第一个定义。

CSS 变量的巧妙之处在于它们与定义变量的元素一起嵌套。因此,如果您有一个<taskbar side="left">SpoPlanMon Shadow DOM 内部,它会将滑块颜色变量重置为绿色,并且嵌套在其中的任何滑块都将变为绿色。

有一个设计建议是让 Web 组件使用作者定义的伪 ID 将 shadow DOM 内的部分暴露给“从外部”进行样式设置。(W3 错误 15196的描述性不是很强,但它是规范错误。)

为了使用伪 ID 来解决这个问题,AppList 使用伪 ID 公开其滚动滑块:

<applist>
  <scroll-wrap>
    <scroll-bar>
      <scroll-slider pseudo="slider" />
    </scroll-bar>
    <scroll-cont>
      <btn app="SpoPlanMon" />
    </scroll-cont>
  </scroll>
</applist>

然后任务栏可以对其进行样式设置:

<taskbar side="right">
  <style scoped>
    taskbar[side="right"] applist:pseudo(slider) {
      /* styles apply to the <scroll-slider> */
    }
  </style>
  <menubtn />
  <applist scrollable>
    <btn app="SpoPlanMon" />
  </applist>
  <tray />
</taskbar>

这很好,因为它将特定于任务栏上下文的样式与任务栏保持在一起。applist 需要在它的滑块上放置一个伪元素,所以如果你重用一个组件,它没有给你需要的所有样式提供伪元素(CSS 很强大,所以它带来了把事情搞砸的强大能力) ,所以我认为组件通常不会暴露很多伪 ID。)

这没有实现,甚至在规范中!事实上,确切的语法可能会改变。所以现在你不能依赖伪 ID 解决方案。CSS变量可能是要走的路。

于 2012-09-19T02:00:59.667 回答
1

如果您使用成熟的Web 组件而不仅仅是 Shadow DOM,您应该能够从 Javascript 获取父任务栏元素。像这样的东西:

<element>
    <template>
        ...
    </template>
    <script>
        if (this !== window) {
            this.lifecycle({
                created: function() {
                    this.parentElement.attributes['side'].nodeValue; // "right"
                }
            });
        }
    </script>
</element>

但是,这使得您不能再在任务栏之外使用 applist 组件,这通常是一件坏事。我们应该尝试使组件尽可能模块化、独立和可重用。问问自己,“关于父元素,我到底需要知道什么?” 你能把应用列表写成

<applist scrollable="right">...

为了在任何你想要的地方使用这个组件的能力,重复是一个很小的代价。谁知道?将来您可能会决定以这样的方式使用任务栏和应用程序列表,side="right"但是scrollable="bottom"

更新

如果你想让 Shadow DOM 元素的样式随着宿主元素的变化而动态变化,你很快就能使用@host @-rule。该规范在这里根本不清楚,但我认为它将像这样使用(取自对 Web Components 的 W3 规范的错误的评论):

@host {
    div { background-color: white; }
    .warning { background-color: yellow; }
    .important .warning { background-color: orange; }
}

这(我认为)会给主机一个默认的白色背景颜色,如果主机有 class ,它将被覆盖为黄色warning如果主机有 class ,它还会在主机内设置一个带有橙色背景颜色的警告元素important

于 2012-09-05T13:29:04.397 回答