将样式导入Web组件

时间:2015-02-22 22:41:43

标签: html5 web-component shadow-dom

将样式导入Web组件的规范方法是什么?

以下给我一个错误HTML element <link> is ignored in shadow tree

<template>
    <link rel="style" href="foo.css" />
    <h1>foo</h1>
</template>

我使用以下方法使用shadow DOM插入此内容:

var importDoc, navBarProto;

importDoc = document.currentScript.ownerDocument;

navBarProto = Object.create(HTMLElement.prototype);
navBarProto.createdCallback = function() {
  var template, templateClone, shadow;

  template = importDoc.querySelector('template');
  templateClone = document.importNode(template.content, true);

  shadow = this.createShadowRoot();
  shadow.appendChild(templateClone);
};

document.registerElement('my-nav-bar', {
  prototype: navBarProto
});

6 个答案:

答案 0 :(得分:9)

如果您需要在<template>标记内放置外部样式,可以尝试

<style> @import "../my/path/style.css"; </style>

但是我觉得这会在创建元素后开始导入

答案 1 :(得分:4)

<强> NB !!!

这个答案已经过时

请通过以下 Himanshu Sharma 检查答案

最新答案:https://stackoverflow.com/a/48202206/2035262

根据Polymer documentation

  

Polymer允许您在<polymer-element>定义中包含样式表,Shadow DOM 本身不支持功能。

这是一个有点奇怪的参考,但我不能直接谷歌。目前看来,没有关于支持模板内部链接的传言。

也就是说,无论您是否想要使用vanilla Web组件,都应该使用<style>标记内嵌css,或者在javascript中手动加载并应用 css 。< /德尔>

答案 2 :(得分:4)

现在,影子dom支持直接<link>标记。

可以直接使用:

<link rel="stylesheet" href="yourcss1.css">
<link href="yourcss2.css" rel="stylesheet" type="text/css">  

它已被 whatwg W3C 批准。

在阴影dom中使用css的有用链接:

直接css链接可用于影子dom。

答案 3 :(得分:1)

上面的答案展示了如何将样式表导入到 Web 组件中,但是可以通过(类似)编程方式将单个样式导入到 shadow DOM 中。这是我最近开发的技术。

首先 - 确保您使用 HTML 代码将组件本地样式直接嵌入到模板中。这是为了确保 shadow DOM 在您的元素构造函数中有一个样式表。 (导入其他样式表应该没问题,但你必须在构造函数中准备好一个)

第二 - 使用 css 变量指向要导入的 css 规则。

#rule-to-import {
   background-color: #ffff00;
}

my-element {
   --my-import: #rule-to-import;
}

第三 - 在组件构造函数中,读取 CSS 变量并在文档样式表中定位指向的样式。找到后,复制字符串但重写选择器以匹配您希望设置样式的内部元素。我为此使用了一个辅助函数。

importVarStyle(shadow,cssvar,target) {
    // Get the value of the specified CSS variable
    const varstyle=getComputedStyle(this).getPropertyValue(cssvar).trim();
    if(varstyle!="") varstyle: {
        const ownstyle=shadow.styleSheets[0];
        for(let ssheet of document.styleSheets) {   // Walk through all CSS rules looking for a matching rule
            for(let cssrule of ssheet.cssRules) {
                if(cssrule.selectorText==varstyle) {    // If a match is found, re-target and clone the rule into the component-local stylesheet
                    ownstyle.insertRule(
                        cssrule.cssText.replace(/^[^{]*/,target),
                        ownstyle.cssRules.length
                    );
                    break varstyle;
                }
            }
        }
    }
}

答案 4 :(得分:0)

可构造样式表

这是一项新功能,允许构造const sheet = new CSSStyleSheet(); 对象。它们可以设置其内容,也可以使用JavaScript从CSS文件中导入,然后将其应用于文档和Web组件的影子根目录。它将在版本73的Chrome中可用,并可能在不久的将来在Firefox中提供。

有一个good writeup on the Google developers site,但下面我将对其进行简要总结,并在底部提供示例。

创建样式表

您可以通过调用构造函数来创建新工作表:

replace

设置和替换样式:

可以通过调用方法replaceSyncreplaceSync来应用样式。 sheet.replaceSync(`.redText { color: red }`); 是同步的,不能使用任何外部资源:

replace

@importasynchronous,可以接受引用外部资源的replace语句。请注意,Promise返回一个sheet.replace('@import url("myStyle.css")') .then(sheet => { console.log('Styles loaded successfully'); }) .catch(err => { console.error('Failed to load:', err); }); ,需要对其进行相应的处理。

adoptedStyleSheets

将样式应用于文档或影子DOM

可以通过设置document或阴影DOM的document.adoptedStyleSheets = [sheet] 属性来应用样式。

adoptedStyleSheets

push()中的数组被冻结,不能用document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet]; 进行突变,但是可以通过结合其现有值来进行串联:

adoptedStyleSheets

从文档继承

影子DOM可以通过以下方式从文档的// in the custom element class: this.shadowRoot.adoptedStyleSheets = [...document.adoptedStyleSheets, myCustomSheet]; 继承构造的样式:

adoptedStyleSheets

请注意,如果此方法在构造函数中运行,则组件将仅继承在其创建之前采用的样式表。在连接每个实例后,connectedCallback中的x-card设置将继承。值得注意的是,这不会引起FOUC

有关Web组件的示例

让我们创建一个名为div的组件,该组件将文本包装为样式优美的// Create the component inside of an IIFE (function() { // template used for improved performance const template = document.createElement('template'); template.innerHTML = ` <div id='card'></div> `; // create the stylesheet const sheet = new CSSStyleSheet(); // set its contents by referencing a file sheet.replace('@import url("xCardStyle.css")') .then(sheet => { console.log('Styles loaded successfully'); }) .catch(err => { console.error('Failed to load:', err); }); customElements.define('x-card', class extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); // apply the HTML template to the shadow DOM this.shadowRoot.appendChild( template.content.cloneNode(true) ); // apply the stylesheet to the shadow DOM this.shadowRoot.adoptedStyleSheets = [sheet]; } connectedCallback() { const card = this.shadowRoot.getElementById('card'); card.textContent = this.textContent; } }); })();

<x-card>Example Text</x-card>
<x-card>More Text</x-card>
import pandas as pd
import os
import time
from datetime import datetime


path = "C:/Users/andre/AppData/Local/Programs/Python/Python37/SciKit-learn Tutorial/intraQuarter"

def Key_Stats(gather = "Total Debt/Equity (mrq)"): 
    statspath = path + '/_KeyStats'
    stock_list = [x[0] for x in os.walk(statspath)]
    counter = 0
    df = pd.DataFrame(columns = ['Date','Unix','Folder','DE Ratio','Price',
                                 'Stock_pct_change','SP500','SP500_pct_change', 'Difference'])

    sp500_df = pd.read_csv("YAHOO-INDEX_GSPC.csv")
    ticker_list = []


    for each_dir in stock_list[1:]:
        each_file = os.listdir(each_dir)
        folder = each_dir.split("\\")[1]
        ticker_list.append(folder)

        #Reset starting point for each directory
        starting_stock_value = False
        starting_sp500_value = False

        if len(each_file) > 0:
            for file in each_file:
                date_stamp = datetime.strptime(file, '%Y%m%d%H%M%S.html')
                unix_time = time.mktime(date_stamp.timetuple())
                full_file_path = each_dir + '/' + file

                file_content_source = open(full_file_path, 'r').read()

                try:
                    value = file_content_source.split(gather)[1].split('<td class="yfnc_tabledata1">')[1].split('</td>')[0]

                    try:
                        sp500_date = datetime.fromtimestamp(unix_time).strftime('%Y-%m-%d')
                        row = sp500_df[(sp500_df['Date'] == sp500_date)] 
                        sp500_value = row['Adj Close']
                        print(type(sp500_value))
                        print(sp500_value)
                    except:    
                        sp500_date = datetime.fromtimestamp(unix_time-259200).strftime('%Y-%m-%d')
                        row = sp500_df[(sp500_df['Date'] == sp500_date)] 
                        sp500_value = row['Adj Close']

                    try:
                        stock_price = file_content_source.split('</small><big><b>')[1].split('</b></big>')[0]
                        if(stock_price.endswith('</span>')):
                           stock_price = stock_price.split('>')[1].split('</span')[0]
                    except IndexError:
                        try:
                            stock_price = file_content_source.split('</small><big><b>')[1].split('</span>')[0].split('>')[1]
                        except IndexError:   
                            try:
                                stock_price = file_content_source.split('<span id="yfs_')
                                seglist = [] #Created a list to store all the possible numbers that arise
                                for parts in stock_price:
                                    segment = parts.split('</span>')[0].split('>')[1]
                                    try:
                                        #The numbers are usually 4,5, or 6 characters in length and check if str is a number
                                        if((len(segment) == 4 or len(segment) == 5 or len(segment) == 6) and float(segment) >= 0):
                                            seglist.append(segment) #Add potential number to list
                                            stock_price = seglist[0] #Noticed the first number is usually the correct one
                                    except ValueError:
                                        pass
                            except IndexError:
                                print('Error in Folder:', folder, ' File: ', file, ' Stock Price=', stock_price)

                    #print('Folder:', folder, ' File', file, ' Stock Price: ', stock_price)

                    if not starting_stock_value:
                        starting_stock_value = float(stock_price)
                    if not starting_sp500_value:
                        starting_sp500_value = float(sp500_value)

                    #percentage change = (new-old)/old x 100
                    stock_pct_change = ((float(stock_price) - starting_stock_value) / starting_stock_value) * 100

   #-------------------------------------------------------------------------------
                    #ERROR OCCURS HERE!!!!
                    sp500_pct_change = ((float(sp500_value) - starting_sp500_value) / starting_sp500_value) * 100

   #-------------------------------------------------------------------------------

                    df = df.append({'Date': date_stamp,'Unix': unix_time,
                                    'Folder': folder,'DE Ratio': value,
                                    'Price': stock_price,
                                    'Stock_pct_change': stock_pct_change,
                                    'SP500': sp500_value,
                                    'SP500_pct_change': sp500_pct_change,
                                    'Difference': stock_pct_change-sp500_pct_change},
                                   ignore_index = True)
                except IndexError:
                    stock_price = file_content_source.split('<span id="yfs_')[5].split('</span>')[0].split('>')[1]
                    print('Error in Folder:', folder, ' File: ', file, "Value=", value, 'Stock Price=', stock_price)

    #Plot
    for each_ticker in ticker_list:
        try:
            plot_df = df[(df['Folder'] == each_ticker)]
            plot_df = plot_df.set_index(['Date'])

            plot_df['Difference'].plot(label = each_ticker)
            plt.legend()
        except:
            pass

    plt.show()


Key_Stats()

答案 5 :(得分:-2)

尝试<style>内的<template>元素:

<template>
    <style>
       h1 { 
         color: red;
         font-family: sans-serif;
       }
    </style>
    <h1>foo</h1>
</template>