在Polymer元素中动态注入共享样式(Polymer 1.2.3)

3
我有几个嵌套的自定义Polymer元素。目前,通过使用Polymer共享样式,我能够将自定义样式注入到其他元素中。不幸的是,这种方法受到静态使用的限制。因此,在实现时,我需要知道哪个元素应该使用哪个共享样式,通过使用<link rel="import" href="my-shared-style.html"><style include="my-shared-style"></style>导入共享样式模块。
但在我的用例中,我需要在运行时将共享样式注入到Polymer元素中。有没有可能实现这一点?
更新:
我尝试了以下方法,受Günters下面的答案启发:
Polymer({
    is : 'html-grid-row',
    /**
    * Inject style into element
    * @param {string} style
    */
    injectStyle : function(style) {
        var customStyle = document.createElement('style', 'custom-style');
        customStyle.textContent = style;
        Polymer.dom(this.root).appendChild(customStyle);
    }
    /**
    * Additional Elements JS functionality is put here...
    *
    */
)}

现在,当我尝试在运行时通过调用injectStyle('div {font-weight: bold;}')来动态添加样式到元素实例时,样式模块会被注入到元素中,但由于Polymer似乎会编辑自定义样式的文本内容,因此它不会被显示出来,如下所示:

<style is="custom-style" class="style-scope html-grid-row">
    div:not([style-scope]):not(.style-scope) {font-weight: bold;}
</style>

有没有办法防止Polymer将:not([style-scope]):not(.style-scope)前缀添加到样式规则中?
更新2:
使用include='my-shared-style'引用全局共享样式具有相同的效果。
包含此静态全局导入的共享样式:
<dom-module id="my-shared-style">
    <template>
        <style>
            div {
                font-weight: bold;
            }
        </style>
    </template>
</dom-module>

在动态导入并引用共享样式Polymer包含以下内容后:
<style is="custom-style" include="my-shared-style" class="style-scope 
 html-grid-row">
    div:not([style-scope]):not(.style-scope) {
        font-weight: bold;
    }
</style> 

解决方案

最终,我采用了一种方法,在运行时通过扩展<style> HTML元素来动态注入样式到Polymer元素中。具体方法是使用document.register('scoped-style', {extends : 'style', prototype : ...})。现在,injectStyle(style)方法(参见上文)直接创建一个<style is="scoped-style">元素作为元素根节点的子元素。实际上,这个方法受到了https://github.com/thomaspark/scoper的启发。目前这种方法对我来说已经有效了。


2
我猜你不能只设置 textContent,而是要使用 custom-styleinclude 属性。我自己不用 JS(只用 Dart),因此很难为我创建适当的 JS 翻译。 - Günter Zöchbauer
我没有深入研究CSS-shim的工作原理。这个重写会引起什么问题? - Günter Zöchbauer
对于 Polymer 元素模板标签内的每个 DOM 节点,都会添加一个名为 style-scope [element name] 的 CSS 类。因此,Polymer 在我的动态添加的 CSS 样式中添加的 :not([style-scope]):not(.style-scope) 伪类会导致这些样式不适用于该 Polymer 元素内部模板标签中包含的 HTML。 - phwa4563
听起来有点奇怪。我没有遇到这样的问题。这不是关于使用<content></content>标签投影的元素吗?您可以尝试使用:host div {作为选择器。 - Günter Zöchbauer
不知道为什么 Polymer 会出现这样的行为。但是目前我有一个适合我的需求的解决方案(请参见上面的解决方案)。尽管如此,我还是支持您在 Polymers GitHub 项目中提出的动态样式请求 :-) - phwa4563
1个回答

5
我曾经成功地使用类似于这样的方法来动态插入样式。
var myDomModule = document.createElement('style', 'custom-style');
myDomModule.setAttribute('include', 'mySharedStyleModuleName');
Polymer.dom(sliderElem.root).appendChild(myDomModule);

需要在某处导入样式模块'mySharedStyleModuleName'(比如index.html)。

有关此方法遇到的问题,请参见https://github.com/Polymer/polymer/issues/2681,有关更多详细信息,请参见https://dev59.com/8pLea4cB1Zd3GeqP6cOA#34650194


1
感谢Günther。听起来是个不错的方法。我明天会尝试一下并提供反馈。 - phwa4563

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接