CSS 可变槽聚合物(动态加载)元件

CSS Variable trough Polymer (dynamically loaded) elements

我的项目中有多个自定义元素,css 变量有问题。在我的 parent 元素中,我有多个状态为 类 的项目元素。我想使用该状态 类 来操作背景和边框颜色,但我想在我的 parent 元素中定义值,但不知何故它不想工作。

这是我的 parent 元素:

<link rel="import" href="app-task.html" />
<dom-module id="app-task-grid">
<template>
    <style>
        :host {
            display: block; position: absolute; left: 0; top: 0; width: 100%; height: 100%;
            overflow:hidden; background: #eee;

            --column-1-width: 80px;
            --column-3-width: 120px;
            --column-4-width: 180px;
            --column-5-width: 220px;
            --column-6-width: 100px;

            --task-background-color: #eee;
            --task-border-color: #ccc;
        }

        :host table.header {
            position: absolute; top: 0; left: 0; width: 100%; height: 40px; background: #DDD;
        }

        :host table.header th {
            letter-spacing: 2px; font-weight: normal; text-transform: uppercase;
            font-size: 80%; border-left: 1px solid #aaa;

            margin: 0; padding: 0 10px;
        }

        :host th.column1 {
            width: var(--column-1-width);
        }

        :host th.column2 {
            text-align: left;
        }

        :host th.column3 {
            width: var(--column-3-width);
        }

        :host th.column4 {
            width: var(--column-4-width);
        }

        :host th.column5 {
            width: var(--column-5-width);
        }

        :host th.column6 {
            width: var(--column-6-width);
            text-align: left;
        }

        :host th.hide, :host td.hide {
            display: none;
        }

        :host th.show, :host td.show {
            display: table-cell;
        }

        :host table.header .scrollbar {
            width: 20px; border-left: none;
            padding: 0;
        }

        :host .items {

            position: absolute; left: 0; top: 40px; right: 0; bottom: 0;
            overflow:hidden; overflow-y: scroll;

            margin: 0; padding: 0;
        }

        :host .items::-webkit-scrollbar {
            width:22px; border-left: 6px solid #ddd;
            background-color:#ddd;
        } 

        :host .items::-webkit-scrollbar-thumb {
            background-color:#aaa;
            border-left: 6px solid #ddd;
            min-height: 80px;
        }

        .waiting {
            --task-background-color: #e9d32c;
            --task-border-color: #b0a030;
        }

        .assigned {
            --task-background-color: #1b7eee;
            --task-border-color: #1357a4;
        }

        .started {
            --task-background-color: #EF6207;
            --task-border-color: #c05d1d;
        }

        .working {
            --task-background-color: #e99c2c;
            --task-border-color: #c48222;
        }

        .aborted {
            --task-background-color: #E34126;
            --task-border-color: #b72d15;
        }
    </style>

    <table class="header">
        <tr>
            <th class="column1"></th>
            <th class="column2">Column#2</th>
            <th class="column3">Column#3</th>
            <th class="column4">Column#4</th>
            <th class="column5">Column#5</th>
            <th class="column6">Column#6</th>
            <th class="scrollbar"></th>
        </tr>
    </table>

    <div class="items">
        <app-task id="task0" class="waiting"></app-task>
    </div>

</template>
<script>
    Polymer({
        is:"app-task-grid",
        loadItems: function()
        {
            let statuses = ['waiting','assigned','started','working','aborted'];
            for(var i = 1; i<=30; i++)
            {
                let itemStatus = statuses[Math.floor(Math.random()*statuses.length)];

                let itemElement = document.createElement('APP-TASK');
                        itemElement.id = 'task'+i;
                        itemElement.classList.add(itemStatus);

                console.debug( itemElement );

                this.querySelector('.items').appendChild( itemElement );
            }
        }
    });
</script>
</dom-module>

我的children元素:

<dom-module id="app-task">
<template>
    <style>
        :host {
            display: block; margin: 8px 0; padding: 0;
        }

        :host table {
            width: 100%; height: 80px;

            background-color: var(--task-background-color, #fff);

            border-bottom: 5px solid var(--task-background-color, #fff);
            border-top: 5px solid var(--task-background-color, #fff);

            box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.07),
                        0 1px 5px 0 rgba(0, 0, 0, 0.06),
                        0 3px 1px -2px rgba(0, 0, 0, 0.1);
        }

        :host table td {
            border-left: 1px solid var(--task-border-color, #ccc);
            margin: 0; padding: 0 10px;
        }

        :host td.column1 {
            width: var(--column-1-width);
        }

        :host td.column2 {

        }

        :host td.column3 {
            width: var(--column-3-width);
        }

        :host td.column4 {
            width: var(--column-4-width);
        }

        :host td.column5 {
            width: var(--column-5-width);
        }

        :host td.column6 {
            width: var(--column-6-width);
        }
    </style>

    <table>
        <tr>
            <td class="column1">C#1</td>
            <td class="column2">C#2</td>
            <td class="column3">C#3</td>
            <td class="column4">C#4</td>
            <td class="column5">C#5</td>
            <td class="column6">C#6</td>
        </tr>
    </table>

</template>
<script>
    Polymer({
        is:"app-task"
    });
</script>
</dom-module>

我已经试过了:

但其中 none 似乎有效。

如果我在 :host 中定义 css 变量,那么它就可以工作,只是不能以某种方式与 类 一起工作。哪里弄错了?


更新#1:

如果我将 "style-scope app-task-grid" 添加到任务的 parent 元素中,style-scope 会出现一些奇怪的问题:

<div class="items">
    <div class="style-scope app-task-grid waiting">
        <app-task id="task1"></app-task>
    </div>
</div>

然后,如果我添加一个正常的 css 规则,例如它在 app-task 中应用的颜色,但 css 变量不是。


更新#2:

因为有人提到这个模板是有效的,我测试了它,它是,!但 id 没有提到项目是动态创建并附加到项目的。我在 Plunker 上添加了我的代码中的几乎所有内容:http://plnkr.co/edit/b5XW1w3sEOy4UHc0rdWH?p=preview

对不起我的误导,我不知道问题根源是动态负载。

注意:我用更多示例更新了问题。


更新#3:

感谢@a1626s 和@GünterZöchbauer,我们找到了答案:

我的初始代码很好,从一开始就可以工作,我定义问题很糟糕,因为我没有看到问题所在。因此,如果有人在元素内部动态加载元素,则必须使用 Polymer.dom api.

Polymer.dom(this.querySelector('.items')).appendCild(itemElement);

请记住,设置 CSS 变量的 <style> 必须在标记中包含 is="custom-style"

我拼凑了一个非常粗略的片段来展示它。

<script src="https://polygit.org/components/webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="https://polygit.org/components/polymer/polymer.html">
<dom-module id="app-task">
  <template>
    <style>
      :host {
        display: block;
        height: 80px;
        margin: 5px;
        background-color: var(--task-background-color, #fff);
        border: 1px solid var(--task-border-color, #ccc);
      }
    </style>
    <div>some stuff...</div>
  </template>
  <script>
    Polymer({
      is: 'app-task'
    });
  </script>
</dom-module>

<!-- Beginning of the 'parent element' -->

<style is="custom-style">
  .waiting {
    --task-background-color: #e9d32c;
    --task-border-color: #b0a030;
  }
  .assigned {
    --task-background-color: #1b7eee;
    --task-border-color: #1357a4;
  }
  .started {
    --task-background-color: #EF6207;
    --task-border-color: #c05d1d;
  }
  .working {
    --task-background-color: #e99c2c;
    --task-border-color: #c48222;
  }
  .aborted {
    --task-background-color: #E34126;
    --task-border-color: #b72d15;
  }
</style>
<div class="items">
  <app-task id="task1" class="waiting"></app-task>
  <app-task id="task2" class="waiting"></app-task>
  <app-task id="task3" class="working"></app-task>
  <app-task id="task4" class="working"></app-task>
  <app-task id="task5" class="assigned"></app-task>
  <app-task id="task6" class="aborted"></app-task>
</div>

另一个例子运行通过几个元素

<script src="https://polygit.org/components/webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="https://polygit.org/components/polymer/polymer.html">
<dom-module id="app-task">
  <template>
    <style>
      :host {
        display: block;
        height: 80px;
        margin: 5px;
        background-color: var(--task-background-color, #fff);
        border: 1px solid var(--task-border-color, #ccc);
      }
    </style>
    <div>some stuff...</div>
  </template>
  <script>
    Polymer({
      is: 'app-task'
    });
  </script>
</dom-module>

<!-- Beginning of the 'parent element' -->

<dom-module id="app-task-grid">
  <template>
    <!-- normal styles -->
    <style>
      app-task {
        width: 50%;
        margin: 10px auto;
      }
    </style>
    <!-- custom styles -->
    <style is="custom-style">
      .waiting {
        --task-background-color: #e9d32c;
        --task-border-color: #b0a030;
      }
      .assigned {
        --task-background-color: #1b7eee;
        --task-border-color: #1357a4;
      }
      .started {
        --task-background-color: #EF6207;
        --task-border-color: #c05d1d;
      }
      .working {
        --task-background-color: #e99c2c;
        --task-border-color: #c48222;
      }
      .aborted {
        --task-background-color: #E34126;
        --task-border-color: #b72d15;
      }
    </style>
    <div class="items">
      <app-task id="task1" class="waiting"></app-task>
      <app-task id="task2" class="waiting"></app-task>
      <app-task id="task3" class="working"></app-task>
      <app-task id="task4" class="working"></app-task>
      <app-task id="task5" class="assigned"></app-task>
      <app-task id="task6" class="aborted"></app-task>
    </div>
  </template>
  <script>
    Polymer({
      is: 'app-task-grid'
    });
  </script>
</dom-module>

<!-- And now pushing it to the screen -->

<app-task-grid></app-task-grid>

我没有发现您的初始代码有任何问题。我复制了您的代码并将其粘贴到 plunker

<style>
    :host {
        display: block;
    }

    .waiting {
        --task-background-color: #e9d32c;
        --task-border-color: #b0a030;
    }

    .assigned {
        --task-background-color: #1b7eee;
        --task-border-color: #1357a4;
    }

    .started {
        --task-background-color: #EF6207;
        --task-border-color: #c05d1d;
    }

    .working {
        --task-background-color: #e99c2c;
        --task-border-color: #c48222;
    }

    .aborted {
        --task-background-color: #E34126;
        --task-border-color: #b72d15;
    }
    </style>

    <div class="items">
        <app-task id="task1" class="waiting"></app-task>
        <app-task id="task2" class="waiting"></app-task>
        <app-task id="task3" class="working"></app-task>
        <app-task id="task4" class="working"></app-task>
        <app-task id="task5" class="assigned"></app-task>
        <app-task id="task6" class="aborted"></app-task>
    </div>

它对我来说似乎工作正常。

至于你的新问题,用这个方法替换你的 javascript 方法,它应该可以工作。

{
  let statuses = ['waiting','assigned','started','working','aborted'];
   for(var i = 1; i<=30; i++)
    {
     let itemStatus = statuses[Math.floor(Math.random()*statuses.length)];

     let itemElement = document.createElement('APP-TASK');
     itemElement.id = 'task'+i;
     itemElement.classList.add(itemStatus);

     console.debug( itemElement );


     Polymer.dom(this.$.items).appendChild(itemElement);

    }
    Polymer.dom.flush();
   }

此外,这是我在您的 app-task-grid 元素中所做的更改

<div class="items" id="items"> //added id attribute to the div tag

问题在于您添加子元素的方式无法将它们正确插入到元素的 dom tree 中。 Polymer 有关于如何使用其元素树的文档。您可以阅读更多相关信息 here