我正在构建一个模块化的网络应用程序,其中要处理各种用户创建的模型。Shadow DOM 是一个明显的选择,但我不明白 JS 如何在 Shadow DOM 中执行。
我有一个 HTML 内容要使用以下虚拟脚本加载。
<h1>Nice header</h1>
<script type="text/javascript">
console.log('hello')
alert('hi');
</script>
Run Code Online (Sandbox Code Playgroud)
我使用之前的脚本加载页面,如下所示:
<div id="shadow-target"></div>
<div id="non-shadow-target"></div>
<script>
// Called on btn click
loadShadow = function(module) {
var root = document.querySelector('#shadow-target').createShadowRoot();
var lighttarget = document.querySelector('#non-shadow-target');
$.get('whatever.html', function (data) {
alert(data);
$(root).append(data); // Nothing executed
$(lighttarget).append(data); // Works fine
// The header appears in both cases
});
}
</script>
Run Code Online (Sandbox Code Playgroud)
正如评论所说,当内容插入到影子 DOM 根时,JS 不会被执行。标头在两种情况下都会出现,但脚本仅在 light DOM 中执行。这是为什么?自定义JS如何在shadow DOM中执行?(没有跨域的东西。)
我创建了一个普通的自定义元素:
document.registerElement("my-el", { prototype: Object.create(HTMLElement.prototype) });
Run Code Online (Sandbox Code Playgroud)
该元素使用 Shadow DOM 和<style>其中的标签。但是,我想让用户在主样式表中定义自定义元素的大小。它通过引用自定义标签来工作,但这是执行此类操作的推荐方法吗?
例如:
my-el {
width: 300px;
height: 50px;
background: green;
}
Run Code Online (Sandbox Code Playgroud) Shadow DOM 支持使用<link>标签来加载样式,其范围与声明的样式相同<style>,这非常方便,但带来的问题是样式仅在准备就绪时才应用,并且在加载样式时存在 FOUC:defined例如,使用自定义元素的伪选择器无法阻止这种情况。我遇到的另一个问题是在构建或连接自定义元素时测量影子根内部的元素,因为在加载和应用样式表后才知道“真实”尺寸,我不知道什么时候会发生这种情况(也许ResizeObserver实施时会有帮助吗?)
任何人都可以想出一种聪明的方法来解决这些问题(无需手动内联样式或使用构建步骤)?我的担心有道理吗?考虑到<link rel="stylesheet>在<head>块渲染中并且此功能应该与此类似,是否可以将其视为错误?
是否可以使用java和selenium找到Shadow DOM的元素?
我想从影子根中获取元素
<paper-input id="homeSearch" class="home-search-btn home-inputs" placeholder="Where would you like to go?" no-label-float="" tabindex="0" aria-disabled="false"><iron-icon icon="-search-" slot="prefix" class="form-icons search-icon"></iron-icon></paper-input>Run Code Online (Sandbox Code Playgroud)
我想发送一个输入,homesearch就像driver.findElement(By.id("homesearch"));我在互联网上搜索但没有得到任何适当的解决方案。
任何类型的帮助将非常感激
当使用用户嵌入的 JSON 字符串创建 HTML 自定义元素时(尽管字符串的类型与此处不相关)...
<my-elem>
{ "some":"content" }
</my-elem>
Run Code Online (Sandbox Code Playgroud)
我想要JSON.parse这样...
class MyElement extends HTMLElement {
constructor() {
super();
this.root = this.attachShadow({ mode:'open' });
this.root.appendChild(template.content.cloneNode(true));
}
connectedCallback() {
JSON.parse(this.innerHTML);
}
}
customElements.define('my-elem', MyElement);
const template = document.createElement('template');
template.innerHTML = `irrelevant`;
Run Code Online (Sandbox Code Playgroud)
...并使用 Firefox v.63 获得完美结果。
但是用 Chrome v.71 运行这个我得到
Uncaught SyntaxError: Unexpected end of JSON input
Run Code Online (Sandbox Code Playgroud)
由于this.innerHTML返回空字符串。
我还尝试了其他 DOM 方法来访问文本内容,但也都失败了。
现在我对如何让它与 Chrome 一起工作一无所知。
顺便说一句:使用<slot>没有任何帮助,因为我不想渲染文本内容......只能访问它进行解析。
解决:
我正在寻找一个通用的解决方案来查找元素的可滚动容器(我想监听滚动事件)。正常的方法是在 DOM 树中向上遍历检查父元素,直到其中一个元素可滚动 -这里有一些类似的解决方案。然而,如果 Shadow DOM 也在图片中,这将会失败。
这是一个示例结构:
<app-home>
<ion-content>
#shadow-root
<div class="inner-scroll">
<slot>
-> <my-element> (reveal)
</slot>
</div>
<my-element>...</my-element>
</ion-content>
</app-home>
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,可滚动元素是.inner-scroll,它位于 的 Shadow dom 内ion-content。由于my-element通过 进入容器slot,向上遍历树将永远不会到达滚动容器(my-element-> ion-content-> app-home)。
我发现它ion-content有一个getScrollElement方法,可以在这种特定情况下使用,但是我想知道是否有一个基于通用 DOM 的解决方案,因为我希望它无论上下文如何都能工作。
更新:
更清楚地说,我希望my-element成为一个独立的、可重用的组件,它可以找到它的滚动容器,无论它放在哪里。我发现,内置scrollIntoView方法适用于 DOM 元素,并且它滚动正确的容器,这意味着浏览器以某种方式找出它,但不会公开返回滚动容器的方法。
另一个想法是在更高级别上侦听滚动事件,而不知道确切的元素,但这也不起作用,因为滚动事件不会传播。
有任何想法吗?
给出以下示例代码:
import { LitElement, html, css } from 'lit-element';
class ItemsDisplay extends LitElement {
static get styles() {...}
static get properties {...}
constructor () {
super();
...
}
render {
return html`
${this.items.map((item, index, array) => html`
<div class="name">
...
</div>
`)}
`;
}
}
Run Code Online (Sandbox Code Playgroud)
选择类“name”的所有节点的适当方法是什么?
我尝试过以下方法,但均失败;所有时间nodesList都是undefined:
constructor : this.nodesList = this.shadowRoot.querySelectorAll(".name");
Run Code Online (Sandbox Code Playgroud)
firstUpdated(changedProperties) {
return this.nodesList = this.shadowRoot.querySelectorAll(".name");
}
Run Code Online (Sandbox Code Playgroud)
getNodesList() {
let nodesList = this.shadowRoot.querySelectorAll(".name");
...
}
Run Code Online (Sandbox Code Playgroud)
我也尝试过:
connectedCallback() {
super.connectedCallback(); …Run Code Online (Sandbox Code Playgroud) 考虑一个使用 shadow DOM 的非常简单的自定义元素:
customElements.define('shadow-element', class ShadowElement extends HTMLElement {
constructor() {
super();
this.styleTag = document.createElement('style');
this.styleTag.textContent= `
.root::before {
content: "root here!";
color: green;
}
`
this.shadow = this.attachShadow({mode: 'closed'});
this.root = null;
}
connectedCallback() {
this.root = document.createElement('div');
this.root.className = 'root';
this.shadow.append(this.root, this.styleTag);
}
})Run Code Online (Sandbox Code Playgroud)
<shadow-element></shadow-element>Run Code Online (Sandbox Code Playgroud)
为了将 CSS 放入 shadow DOM,我创建了一个style标签,并将其附加到 shadow root 中。到目前为止,这一切都很好。
现在对于更复杂的 CSS,我想shadow-element.css在与 .css 文件位于同一文件夹中的文件中编写它shadow-element.js。除了关注点的分离, 我还需要 IDE 语法突出显示和 CSS 创作的完成,所以我真的希望将 CSS 放在一个单独的专用文件中。
我想将该 CSS 文件的内容导入到 Javascript 变量中,例如
import …Run Code Online (Sandbox Code Playgroud) 我有一个丰富的编辑器,我正在重写为一个 lit-element 自定义元素。我正在使用 Firefox(最新)进行测试。我正在尝试在自定义元素的 shadowDom 中(在方法中)获取内容可编辑元素的选择。
在 Firefox 调试器中),this.shadowRootshadowRoot 元素看起来是正确的,但this.shadowRoot.getSelection没有定义,即使DocumentOrShadowRoot
说shadowRoot.getSelection()是在 shadow DOM 中获取选择的正确方法。任何人都可以阐明我缺少的东西吗?
非常感谢!
shadow-dom ×10
javascript ×4
css ×2
lit-element ×2
dom ×1
es6-modules ×1
html ×1
html-heading ×1
ionic4 ×1
java ×1
lit ×1
polymer ×1
selenium ×1
styles ×1
webpack ×1
xpath ×1