背景:这个问题与 Chrome 最新版本扩展的开发有关。它依赖于 javascript 功能,例如并非在所有浏览器上都可用的 HTML 导入和自定义元素,但在这种情况下是可以的。
我正在尝试实现一个简化的 HTML 自定义元素,如下所示:
<custom-el>
<span slot="head">Great</span>
<span slot="item">Item one</span>
<span slot="item">Item two</span>
<span slot="foot">done</span>
</custom-el>
Run Code Online (Sandbox Code Playgroud)
我注册了<custom-el>. 每次创建元素时,我的代码的自定义元素类都会附加一个影子根并附加到以下模板中的影子根内容:
<template id="main">
<h1><slot name="head"></slot></h1>
<ul>
<slot name="item"></slot>
</ul>
<i><slot name="foot"></slot></i>
</template>
Run Code Online (Sandbox Code Playgroud)
我想将每个<span>属性重新分配slot="item"给负责呈现单个项目的辅助模板:
<template id="sub">
<li><slot name="item"></slot></li>
</template>
Run Code Online (Sandbox Code Playgroud)
带属性的槽数name="item"不固定。它从数据库生成并定期更改。
我知道可以通过将 shadowRoot 附加到插槽的父元素并设置插槽的插槽属性来重新分配插槽,例如<slot name="item" slot="newItem">. 但我认为这在我的情况下不起作用,因为子模板需要包装每个项目实例,而不是项目列表。
我可以将影子根和子模板附加到主文档中的每个项目。这会起作用,但我的偏好是主模板导入并应用任何嵌套的 shadowRoots 和模板。这样,主文档只需要导入包含主模板的文件。组件细节的实现被封装在主模板html文件中。
我还可以使用slotchange事件和HTMLSlotElement.assignedNodes方法来拼凑脚本解决方案。但我宁愿不走那条路。
还有另一种方法吗?我的实际用例涉及更复杂的 HTML 结构。或者我的架构或对 Web 组件的理解有缺陷?
html web-component google-chrome-extension shadow-dom custom-element
我有一个自定义元素(没有 shadow DOM),我希望能够在任何地方使用,甚至在另一个可能使用 shadow DOM 的自定义元素中。但是,我不确定如何让样式在这两个地方都有效。
例如,假设我创建了一个简单的fancy-button元素:
class fancyButton extends HTMLElement {
constructor() {
super();
this.innerHTML = `
<style>
fancy-button button {
padding: 10px 15px;
background: rgb(62,118,194);
color: white;
border: none;
border-radius: 4px
}
</style>
<button>Click Me</button>`;
}
}
customElements.define('fancy-button', fancyButton);Run Code Online (Sandbox Code Playgroud)
<fancy-button></fancy-button>Run Code Online (Sandbox Code Playgroud)
在 shadow DOM 元素内,插入的样式标签将允许fancy-button样式工作。但是,如果在 shadow DOM 元素之外使用此组件,则每次使用该元素时都会复制样式标记。
相反,如果我将样式标记添加为 html 导入文件的一部分,那么样式只能在 shadow DOM 之外工作,但至少它们只声明一次。
<!-- fancy-button.html -->
<style>
fancy-button button {
padding: 10px 15px;
background: rgb(62,118,194);
color: white;
border: none;
border-radius: 4px
}
</style>
<script> …Run Code Online (Sandbox Code Playgroud) 我想将 CSS 样式应用于 SVG 元素内的 SVG<defs>元素。虽然在 Chrome 和 Internet Explorer(版本 11)中,以下代码可以正常工作,但在 Firefox 中却不能。如何将样式应用于defsFirefox 中的 SVG 元素?
#symbolcontainer.green #mysymbol { fill: green; }Run Code Online (Sandbox Code Playgroud)
<svg>
<g id="symbolcontainer" class="green">
<defs>
<g id='mysymbol'>
<defs>
<circle id="myCircle" r="2" cx="2" cy="2"/>
</defs>
<use href="#myCircle"/>
</g>
</defs>
<use href="#mysymbol" />
</g>
</svg>Run Code Online (Sandbox Code Playgroud)
在 chrome 和 Internet Explorer 中,圆圈为绿色(已应用样式),而在 Firefox 中为黑色(未应用样式)。
查看并使用此小提琴进行测试。
我在 stackoverflow 上搜索了“svg firefox style defs”,但没有找到我的问题的答案。
我正在尝试使用 Java Selenium 在我的节点 webkit 应用程序上自动化一些测试。它的工作方式是 chromedriver 附加到主窗口,但我访问的任何站点都作为 webview 在 DOM 中,如下所示:
带有 DOM 的图片:

我将如何处理这个问题?在 java 中扩展 shadow root 元素并尝试将上下文切换到它下面的 iframe 之后,我只是得到与我正在调用的函数无关的随机错误(在我看来)。例如:
WebElement shadowRoot = expandShadowElement(root);
WebElement iframe = shadowRoot.findElement(By.cssSelector("iframe"));
Driver.getWebDriver().switchTo().frame(iframe);
WebElement city = Driver.getWebDriver().findElement(By.className("input-btn-group"));
Run Code Online (Sandbox Code Playgroud)
第二行给了我一个“isShown 的参数必须是元素类型”,但这没有意义,因为我没有调用 isShown 函数。
我想做一个Angular 7应用程序,所有encapsulation设置都为ViewEncapsulation.ShadowDom- 这一切都很好。
但我似乎无法找到任何可靠的参考资料,可以很好地解决像@angular/material. 由于全局样式毫无价值,我不能只遵循Theming Angular Material的规则,因为它们......好吧,不起作用。
有没有人设法让它以一种体面的方式工作?
我正在使用 playsinline 属性在页面上显示一个元素,以允许 iOS 设备播放视频而不将其设置为全屏。效果很好,但我注意到,使用该属性,视频元素包含一个带有“媒体控件容器”类的 div 的“阴影内容(用户代理)”元素,这让我认为它与视频控件有关酒吧 o 相似。该 div 通常不会打扰我,但我尝试在视频元素的容器上添加一个点击侦听器,我注意到如果我点击视频元素表面,则不会触发该事件,这在桌面上运行良好浏览器代替。
我已经尝试在视频元素上设置 css 属性“poiter-events:none”,但这似乎还不够,因为我之前提到的“media-controls-container”阻止了事件传播到下层容器。我发现在“media-controls-container”上设置相同的属性可以解决我的问题,但由于它是“Shadow Content (User Agent)”的一部分,我不知道如何使用 css 设置属性.
我还尝试使用 javascript 检查视频元素,我注意到元素上的“video.shadowRoot”属性设置为 null,据我所知,这意味着阴影内容已关闭且无法访问。
所以基本上我无法更改该阴影内容的 css 属性,并且我不知道如何让视频元素将点击事件传播到父容器。
有谁知道如何做到这一点?另请注意,视频元素相对于其容器使用“位置:绝对”定位(我不知道了解它是否有用)。
谢谢您的帮助。
我尝试将 tinyMCE 初始化为放置在 shadowDOM 中的元素。(聚合物网络组件),但它不起作用。
我在这里找到的情况相同的例子:https : //embed.plnkr.co/WXtcz2GUpOhgrhWBTcAW/
你有什么想法,如何为shadowDOM中的元素初始化tinyMCE 4.9.3?(在 FireFox 65.0.2、Chrome 72.0.3626.121 上测试)
我的网站上安装了一个 Angular Web 组件。它使用 Shadow DOM,因此速度非常快(在我的情况下必须如此)。
在我的网站上,我还有一个快捷方式,h可以打开一个显示一些有用信息的弹出窗口。这个h键绑定必须保持原样。它是如何实现的示例代码可以在这里看到:https : //jsfiddle.net/js1edv37/
这是一个简单的事件侦听器,用于侦听document:
$(document).on("keyup", function(e) {
}
Run Code Online (Sandbox Code Playgroud)
但是,当我的 Web 组件具有焦点textarea或input元素时,这也会被触发。发生这种情况是因为它使用了来自外部的脚本无法访问的 Shadow DOM。
您可以通过按下和元素h内部和外部的键盘来测试它。inputtextarea
有没有办法让我的脚本从 Shadow DOM Web 组件外部仍然监听keyup事件,但让它监听页面上的所有元素?即使是 Shadow DOM 中的那些。
我将与 Angular 7 上的 Angular Elements 取得联系,以构建可以简单地部署在现有网页中的轻量级 Web 组件。第一次测试很有希望,但是我在使用基于 Angular Material (MatDialog) 的对话框时遇到了显示问题。如果我将 Angular 组件 (FilterComponent) 构建为 Angular 元素并在简单的 HTML5 网页中运行生成的 Web 组件,则对话框将直接显示在基础网页上,而不是分离的框。
我使用当前稳定版本的 Angular/cli 7.3.8。
app.module.ts:
@NgModule({
declarations: [
AppComponent,
SearchElementComponent,
FilterDialogComponent,
FilterComponent,
],
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
MaterialModule,
ReactiveFormsModule,
],
entryComponents: [SearchElementComponent, FilterComponent, FilterDialogComponent]
})
export class AppModule {
constructor(private injector: Injector) {
}
ngDoBootstrap() {
// Convert `SearchElementComponent` to a custom element.
const SearchElementElement = createCustomElement(SearchElementComponent, {injector: this.injector});
// Register the custom element with the browser. …Run Code Online (Sandbox Code Playgroud) 我正在尝试封装嵌入式组件的样式。该组件必须防止站点在没有脚本的情况下轻松覆盖样式。选择 Shadow Dom 的用途类似于Web Components。
然而,这会给 webpack 中的样式带来问题。所有样式都必须使用import 'style.css'从每个单独的组件导入而无需修改。
style-loader的insertInto选项旨在帮助解决此问题,但这只会引起更多问题。
...
use: [
{
loader: 'style-loader',
options: {
insertInto: () => document.getElementById('host').shadowRoot
},
},
{loader: 'css-loader'},
],
...
Run Code Online (Sandbox Code Playgroud)
它产生错误:
未捕获的不变违规:目标容器不是 DOM 元素。
不确定该项目是否已加载我创建了文件来管理它(纯 javascript,因此 webpack 配置可以使用它):
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getShadow = exports.getRoot = void 0;
var getShadow = function getShadow() {
if (getShadow.root != null) {
// Create the shadow root.
var pageRoot = document.getElementById('host');
pageRoot.attachShadow({
mode: 'open' …Run Code Online (Sandbox Code Playgroud) shadow-dom ×10
html ×3
angular ×2
javascript ×2
angular7 ×1
css ×1
dialog ×1
element ×1
firefox ×1
html5-video ×1
iframe ×1
ios ×1
java ×1
jquery ×1
polymer-1.0 ×1
reactjs ×1
selenium ×1
semantic-ui ×1
svg ×1
tinymce ×1
webpack ×1
webview ×1