Dart 如何从全局命名空间访问聚合元素中的DOM元素?
我想从my app.dart global访问my-app-as-an-element.html中的DOM元素(因为这是一个我想从多个地方调用的方法,例如,它会更改页面标题),但由于它被包装在阴影中,所以我似乎无法访问它。有一个窍门要做Dart 如何从全局命名空间访问聚合元素中的DOM元素?,dart,polymer,dart-polymer,Dart,Polymer,Dart Polymer,我想从my app.dart global访问my-app-as-an-element.html中的DOM元素(因为这是一个我想从多个地方调用的方法,例如,它会更改页面标题),但由于它被包装在阴影中,所以我似乎无法访问它。有一个窍门要做 HtmlElement el; el = document.querySelector('body /deep/ #page-title'); 但是/deep/在Safari中不受尊重,所以这是不可能的。想法?您试图做的事情与Polymer的理念背道而驰:所有
HtmlElement el;
el = document.querySelector('body /deep/ #page-title');
但是/deep/在Safari中不受尊重,所以这是不可能的。想法?您试图做的事情与Polymer的理念背道而驰:所有封装的要点,使用Shadow DOM等,是让可重用组件管理自己的状态,包括DOM 如果拥有您试图访问的DOM元素的元素是自定义元素(即您或您公司的某个人编写的),那么最好的解决方案是将您需要的功能作为该元素上的公共方法公开 例如,假设您的元素有一个
,您希望更改其内容。您可以通过以下方式实现这一点:
Polymer("my-custom-element", {
changeTitle: function(newTitle) {
// this operates on the element's Shadow DOM *only*,
// NOT the entire page
document.querySelector('h1').htmlContent = newTitle;
}
})
然后,您可以使用全局代码进行此调用:
document.querySelector("my-custom-element").changeTitle("My New Title");
如果您试图更改的元素属于公共元素(例如,来自核心元素
或纸质元素
),或者您从某个存储库下载的任何内容,请阅读文档,看看它是否以某种方式公开了您需要的功能。如果没有,您可以尝试编写自己的自定义元素来创建该元素。在扩展元素中,可以使用
标记插入extendee的shadowDOM,并通过元素的JavaScript以与上述相同的方式对其进行操作
编辑:事实上,有一种方法可以直接做你想做的事情,尽管我只建议作为最后的手段。如果阅读,您会注意到可以通过.shadowRoot
属性访问元素的阴影DOM。这将为您提供另一个文档
对象,您可以在该对象上再次使用.querySelector
,如下所示:
document.querySelector('my-custom-element').shadowRoot.querySelector('h1');
甚至
document.querySelector('my-custom-element::shadow h1');
这为您提供了元素的句柄,您可以根据需要对其进行修改。但是,我再次建议不要使用此选项,除非您需要快速访问此元素以进行调试。
querySelector中的/deep/
Polyfill正在进行中,不久将在不支持本机Shadow DOM的浏览器上提供。!如果我有我的应用程序,其中有子元素,我想从那里调用我的app.changetTitle(),该怎么办?我应该将我的应用程序类导入子元素以便调用其方法,还是使用您的第一个解决方案?奇怪的是,你为什么不推荐第二种和第三种解决方案呢?更新后的答案会让人震惊。要进一步扩展,如果我将我的应用程序类导入子元素以便调用其方法,那么IDE将自动完成并识别该方法,而对于document.querySelector('my-app').myMethod(),“该方法不是为class元素定义的”。但是,将父元素导入子元素有缺点吗?不管怎么说,这似乎很奇怪。事实上,对我来说,最干净的方法似乎是将changetTitle()
方法放入应用程序全局,然后使用document.querySelector('my-App-as-an-element::shadow#page title')与元素交互
然后我可以从导入应用程序的任何地方调用app.changetTitle(),但为什么你说这不推荐?@DavidNotik我不确定“将我的应用程序类导入子元素”是什么意思,你能澄清一下吗?@DavidNotik我建议将changetTitle()方法放在包含要更改的标题的元素上。这将使其成为其公共界面的一部分,因此您可以执行类似于document.querySelector('my-element').changetTitle(“任意”)
的操作。如果可能的话,您不应该从外部访问另一个元素的shadowdom的原因是封装:shadowdom应该是“私有”内容,由拥有它的元素来管理。事实上,在这里需要注意这一点。我的问题是如何在没有这一点的情况下实现这一点(特别是考虑到它目前缺乏支持),而另一个答案表明,无论如何,我应该以不同的方式思考这一点。