zoukankan      html  css  js  c++  java
  • LitElement(三)Styles样式

    1、为组件添加样式

    import { LitElement, css, html } from 'lit-element';
    
    class MyElement extends LitElement {
      static get styles() {
        return css`
          div { color: red; }
        `;
      }
      render() { 
        return html`
          <div>I'm styled!</div> 
        `;
      }
    }

    如同 static get properties()属性一样,这是另一个静态属性 static get styles(),专门用来定义组件的样式属性,css是如同html一样的另一个父类函数

    您添加到组件中的样式使用阴影DOM限定范围,不会被用于其他节点。

    1.1 单个样式

    直接返回模板字符串

    static get styles() {
      return css`...`;
    } 

    1.2 多个样式

    返回一个数组

    static get styles() {
      return [ css`...`, css`...`];
    }

    2、在样式中使用表达式

    就像在html内容中使用属性一样

    import { LitElement, html, css } from 'lit-element';
    
    const mainColor = css`red`;
    
    class MyElement extends LitElement {
      static get styles() {
        return css`
          div { color: ${mainColor} }
        `;
      }
      render() {
        return html`<div>Some content in a div</div>`;
      }
    }
    
    customElements.define('my-element', MyElement);

    3、继承样式

    可以从父类继承样式斌不过添加当自己的样式属性

    父类:super-element.js

    import { LitElement, html, css } from 'lit-element';
    
    export class SuperElement extends LitElement {
      static get styles() {
        return css`
          button {  200px; }
        `;
      } 
    
      render() {
        return html`
          <button>click</button>
        `;
      }
    }
    
    customElements.define('super-element', SuperElement);

    子类:my-element.js

    import { css } from 'lit-element';
    import { SuperElement } from './super-element.js';
    
    class MyElement extends SuperElement {
      static get styles() {
        return [
          super.styles,
          css`button { color: red; }`
        ];
      } 
    }
    
    customElements.define('my-element', MyElement);

    4、共享样式

    您可以通过创建导出标签样式的模块来在组件之间共享样式:

    button-styles.js

    import { css } from 'lit-element';
    
    export const buttonStyles = css`
      .blue-button {
        color: white;
        background-color: blue;
      }
      .blue-button:disabled {
        background-color: grey;
      }`;

    在其他组件中引用它

    import { buttonStyles } from './button-styles.js';
    
    class MyElement extends LitElement {
      static get styles() {
        return [
          buttonStyles,
          css`
            :host { display: block;
              border: 1px solid black;
            }`
        ]
      }
      ...
    }

    5、Shadow DOM样式概述

    本节简要概述了影子DOM样式。

    添加到组件的样式可能会影响:

    • 阴影树(您组件的渲染模板)。
    • 组件本身。
    • 组件的子元素。

    5.1 设置阴影树的样式

    LitElement模板默认情况下渲染到阴影树中。范围限于元素的阴影树的样式不会影响主document或其他阴影树。同样,除了继承的CSS属性外,document级样式不会影响阴影树的内容。

    当您使用标准CSS选择器时,它们仅与组件的阴影树中的元素匹配,这就是组件的封装思想之一。

    import { LitElement, html, css } from 'lit-element';
    
    class MyElement extends LitElement {
      static get styles() {
        return css`
          * { color: red; }
          p { font-family: sans-serif; }
          .myclass { margin: 100px; }
          #main { padding: 30px; }
          h1 { font-size: 4em; }
        `;
      }
      render() {
        return html`
          <p>Hello World</p>
          <p class="myclass">Hello World</p>
          <p id="main">Hello World</p>
          <h1>Hello World</h1>
        `;
      }
    }
    
    customElements.define('my-element', MyElement);

    5.2 ::host 设置组件本身的样式

    您可以使用特殊的 :host 选择器来设置组件本身的样式。(拥有或“ :hosts ”一个阴影树的元素称为宿主元素。)

    要为 host 元素创建默认样式,请使用 :host CSS伪类和 :host()CSS伪类函数。

    • :host选择宿主元素。
    • :host(selector) 选择宿主元素,但前提是宿主元素与选择器匹配。

    my-element.js

    import { LitElement, html, css } from 'lit-element';
    
    class MyElement extends LitElement {
      static get styles() {
        return css`
          /* Selects the host */
          :host { 
            display: block; 
          }
    
          /* Selects the host element if it is hidden */
          :host([hidden]) { 
            display: none; 
          }
    
          /* Selects the host element if it has class "blue" */
          :host(.blue) { 
            background-color: aliceblue;
            color: blue;
          }
        `;
      }
      render() {
        return html`
          <p>Hello World</p>
        `;
      }
    }
    
    customElements.define('my-element', MyElement);

    index.html

    <html>
      <head>
        <title>lit-element code sample</title>
        <script type="module" src="./my-element.js"></script>
      </head>
      <body>
        <my-element></my-element>
        <my-element hidden></my-element>
        <my-element class="blue"></my-element>
      </body>
    </html>

    结果是第一个my-element正常显示,第二个隐藏,第三个以指定颜色显示

    请注意,host 元素也可能会受到阴影树外部的样式的影响,因此,您应将在 :host :host() 规则中设置的样式视为可以被用户覆盖的默认样式。例如:

    my-element {
      display: inline-block;
    }

    5.3 ::slotted设置组件子节点的样式

    您的组件可以接受子节点(例如<ul>元素可以具有<li>个子节点)。要渲染子节点,模板需要包括一个或多个<slot>元素,如使用slot元素渲染子节点中所述。

    使用 ::slotted() CSS伪元素通过<slot> s选择包含在模板中的子节点

    • ::slotted(*) 匹配所有slotted 的元素。
    • ::slotted(p)匹配slotted <p>标签。
    • p ::slotted(*)匹配slotted 元素,其中<slot>是<p>元素的子元素。

    例如:

    import { LitElement, html, css } from 'lit-element';
    
    class MyElement extends LitElement {
      static get styles() {
        return css`
          ::slotted(*) { font-family: Roboto; }
          ::slotted(p) { color: blue; }
          div ::slotted(*) { color: red; }
        `;
      }
      render() {
        return html`
          <slot></slot>
          <div><slot name="hi"></slot></div>
        `;
      }
    }
    customElements.define('my-element', MyElement);

    html

    <html>
      <head>
        <title>lit-element code sample</title>
        <script type="module" src="./my-element.js"></script>
      </head>
      <body>
        <my-element>
          <p>Slotted paragraph</p>
          <span slot="hi">Slotted span inside a div</span>
        </my-element>
      </body>
    </html>

    第一个匹配所有子元素,第二个匹配  <p>Slotted paragraph</p> 它应该是蓝色,第三个匹配父元素为 div, name= "hi" 的标签,也就是 <span slot="hi">Slotted span inside a div</span>,应该是红色

    请注意,只能使用 ::slotted() 设置直接匹配的子元素的样式。

    <my-element>
      <div>Stylable with ::slotted()</div>
    </my-element>
    
    <my-element>
      <div><p>Not stylable with ::slotted()</p></div>
    </my-element>

    另外,可以从阴影树之外设置子样式,因此,应将 ::slotted() 样式视为可以覆盖的默认样式。

    my-element div {
      // Outside style targetting a slotted child can override ::slotted() styles
    }

     5.4 具有自定义属性的可配置样式

    静态样式每个类评估一次。使用CSS变量和自定义属性来制作可以在运行时配置的样式:

    static get styles() {
      return css`
        :host { color: var(--themeColor); }
      `;
    } 
    <style>
      html { 
        --themeColor: #123456;
      }
    </style>
    <my-element></my-element>

    6、在模板中定义范围样式

    我们建议使用静态样式以获得最佳性能。但是,有时您可能需要在LitElement模板中定义样式。有两种方法可以在模板中添加范围样式

    • 使用<style>元素添加样式。
    • 使用外部样式表添加样式。

    每种方式分别有其自己的优点和缺点。

    6.1 使用style元素

    我们建议使用静态样式以获得最佳性能。但是,静态样式每个类解释一次(类属性)。有时,您可能需要解释每个实例的样式(对象属性)。

    我们建议使用CSS属性来创建可自定义的样式。但是,您也可以在LitElement模板中包括<style>元素。这些将根据实例进行更新。

    render() {
      return html`
        <style>
          /* updated per instance */
        </style>
        <div>template content</div>
      `;
    }

    6.2 style元素与表达式

    直接解释每个实例的样式有一些重要的限制和性能问题。反面例子

    // Anti-pattern!
    render() {
      return html`
        <style>
          :host {
            /* Warning: this approach has limitations & performance issues! */
            color: ${myColor}
          } 
        </style>
        <div>template content</div>
      `;
    }

    由于ShadyCSS polyfill的限制,<style>元素内的表达式在ShadyCSS中不会按实例更新。有关更多信息,请参见ShadyCSS

    此外,对<style>元素内部的表达式求值效率低下。当<style>元素内的任何文本更改时,浏览器都必须重新解析整个<style>元素,从而导致不必要的工作。

    如果需要计算<style>元素内的表达式,请使用以下策略来避免产生性能问题:

    • 将需要按实例解释的样式与不需要按实例解释的样式分开。
    • 通过创建一个在完整的<style>块内捕获该属性的表达式来解释每个实例的CSS属性,将其包含在模板中。

    例如:

    import { LitElement, html } from 'lit-element';
    
    const perClassStyle = html`
      <style>
        :host {
          display: block;
          font-family: Roboto;
          font-size: 14px; 
        }
      </style>
    `;
    
    const blueText = html`
      <style> :host { color: blue; } </style>
    `;
    
    const redText = html`
      <style> :host { color: red; } </style>
    `;
    
    class MyElement extends LitElement {
      constructor() {
        super();
        this.perInstanceStyle = redText;
      }
      render() {
        return html`
          ${perClassStyle}
          ${this.perInstanceStyle}
          <div>Hello World</div>
        `;
      }
    }
    
    customElements.define('my-element', MyElement);

    定义了三个完整的<style>块样式表达式,然后分别作为类样式和实例样式

    6.3 引入外部样式表

    我们建议您将样式放在静态样式属性中,以获得最佳性能。但是,您可以在模板中使用<link>包含外部样式表:

    外部css文件app-styles.css

    :host {
      display: block;
      color: blue;
    }
    div { 
      background: aliceblue; 
    }
    button { 
      width: 200px; 
    }

    my-element.js

    import { LitElement, html } from 'lit-element';
    
    class MyElement extends LitElement {
      render() {
        return html`
          <link rel="stylesheet" href="./app-styles.css">
          <button>a button</button>
          <div>a div</div>
        `;
      }
    }
    
    customElements.define('my-element', MyElement);

    index.html

    <html>
    <head>
      <title>lit-element code sample</title>
      <script type="module" src="./my-element.js"></script>
    </head>
    <body>
      <my-element></my-element>
    </body>
    </html>

    但是,有一些重要警告:

    • ShadyCSS polyfill不支持外部样式表。
    • 外部样式在加载时可能导致内容未显示样式(FOUC)闪烁。
    • href属性中的URL是相对于主文档的。如果您正在构建应用程序并且资源URL是公开,那么毫无问题,但是在构建可重用元素时避免使用外部样式表。

    7、动态类和样式

    使样式动态化的一种方法是将绑定添加到模板中的 class 或 style 属性。

    lit-html库提供了两个指令 classMap 和 styleMap ,以方便地在HTML模板中应用类和样式。

    有关这些和其他lit-html指令的更多信息,请参见lit-html内置指令的文档

    要使用 styleMap 或者 classMap

    7.1.导入styleMap 或者 classMap

    import { classMap } from 'lit-html/directives/class-map';
    import { styleMap } from 'lit-html/directives/style-map';

    7.2.在模板中使用styleMap 或者 classMap

    import { LitElement, html, css } from 'lit-element';
    import { classMap } from 'lit-html/directives/class-map';
    import { styleMap } from 'lit-html/directives/style-map';
    
    class MyElement extends LitElement {
      static get properties() {
        return {
          classes: { type: Object },
          styles: { type: Object }
        }
      }
      static get styles() {
        return css`
          .mydiv { background-color: blue; }
          .someclass { border: 1px solid red; }
        `
      }
      constructor() {
        super();
        this.classes = { mydiv: true, someclass: true };
        this.styles = { color: 'green', fontFamily: 'Roboto' };
      }
      render() {
        return html`
          <div class=${classMap(this.classes)} style=${styleMap(this.styles)}>
            Some content
          </div>
        `;
      }
    }
    
    customElements.define('my-element', MyElement);

    渲染结果是这样

    <div class="mydiv someclass" style="color: green; font-family: Roboto;">
        Some content
    </div>

    7.3 classMap语法

    <div class=${classMap({alert:true,info:true})}>Content.</div>
    <!-- Equivalent: <div class="alert info">Content.</div> -->

    例如:

    my-element.js

    import { LitElement, html, css } from 'lit-element';
    import { classMap } from 'lit-html/directives/class-map';
    
    class MyElement extends LitElement {
      static get styles() {
        return css`
          .alert {
            font-family: Roboto;
            font-size: 16px;
            padding: 24px; 
            margin: 12px;
            background-color: whitesmoke;
          }
          .warning {
            color: red;
          }
          .info {
            color: blue;
          }
        `;
      }
      
      render() { 
        return html`
          <div class=${classMap({alert:true,info:true})}>Content.</div>
        `;
      }
    
      // Equivalent: 
      /* 
      render() {
        return html`
          <div class="alert info">Content.</div>
        `;
      }
      */
    
    }
    customElements.define('my-element', MyElement);

    index.html

    <html>
      <head>
        <script src="./my-element.js" type="module"></script>
      </head>
      <body>
        <my-element></my-element>
      </body>
    </html>

    7.4 styleMap语法

    styleMap将一组CSS规则应用于HTML元素:

    <button style=${styleMap({
      backgroundColor: 'blue',
      border: '1px solid black'
    })}>A button</button>
    
    <!-- Equivalent: 
      <button style="
        background-color:blue;
        border: 1px solid black;
      ">A button</button>
    -->

    example:

    import { LitElement, html, css } from 'lit-element';
    import { styleMap } from 'lit-html/directives/style-map';
    
    class MyButton extends LitElement {
      render() { 
        return html`
          <button style=${styleMap({
            backgroundColor: 'blue',
            border: '1px solid black'
          })}>A button</button>
        `;
      }
    
      //Equivalent: 
      /*
      render() {
        return html`
          <button style="
            background-color:blue;
            border:1px solid black
          ">A button</button>
        `;
      }
      */
    }
    customElements.define('my-button', MyButton);

    简而言之,calssMap是通过类选择器绑定样式,而styleMap是行内样式

    注意:

    • 若要引用带连字符的属性(例如font-family),请使用等效的camelCase(fontFamily)或将带连字符的属性名称加引号('font-family')。
    • 要引用自定义CSS属性(例如--custom-color),请将整个属性名称放在引号('--custom-color')中。

    例如,使用内联样式语法:

    <div style="
      background-color:blue;
      font-family:Roboto;
      --custom-color:#e26dd2;
      --otherCustomColor:#77e26d;">
    </div>

    等效的CSS语法:

    div {
      background-color: blue;
      font-family: Roboto;
      --custom-color: #e26dd2;
      --otherCustomColor: #77e26d;
    }

    等效的styleMap语法:

    html`
      <div style=${styleMap({
        'background-color': 'blue',
        fontFamily: 'Roboto',
        '--custom-color': '#e26dd2',
        '--otherCustomColor': '#77e26d'
      })}></div>
    `

    8、主题化

    使用CSS继承将样式信息传播到LitElement组件及其呈现的模板。

    <style>
      html {
        --themeColor: #123456;
        font-family: Roboto;
      }
    </style>
    
    <!-- host inherits `--themeColor` and `font-family` and
         passes these properties to its rendered template -->
    <my-element></my-element>

    使用CSS变量和自定义属性可按实例配置样式。

    <style>
      html {
        --my-element-background-color: /* some color */;
      }
      .stuff {
        --my-element-background-color: /* some other color */;
      }
    </style>
    <my-element></my-element>
    <my-element class="stuff"></my-element>
    // MyElement's static styles
    static get styles() {
      return css`
        :host {
          background-color: var(--my-element-background-color);
        }
      `;
    }

    8.1 CSS继承

    CSS继承允许父元素和宿主元素将某些CSS属性传播到其后代。

    并非所有CSS属性都可被继承。继承的CSS属性包括:

    • color 和 background-color
    • font-family 和其他 font-* 属性
    • 所有CSS自定义属性(--*)

    有关更多信息,请参见MDN上的CSS继承

    您可以使用CSS继承在其后代继承的祖先元素上设置样式:

    <style>
    html { 
      font-family: Roboto;
    }
    </style>
    <div>
      <p>Uses Roboto</p>
    </div>

    同样,宿主元素将可继承的CSS属性传递给它们的影子树。

    <style>
      my-element { font-family: Roboto; }
    </style>
    <my-element></my-element>
    class MyElement extends LitElement {
      render() { 
        return html`<p>Uses Roboto</p>`; 
      }
    }

    example:

    my-element.js

    import { LitElement, html, css } from 'lit-element';
    
    class MyElement extends LitElement {
      render() { 
        return html`<p>Will also use Roboto</p>`; 
      }
    }
    customElements.define('my-element', MyElement);

    index.html

    <html>
      <head>
        <title>lit-element code sample</title>
        <script type="module" src="./my-element.js"></script>
        <style>
          my-element { font-family: Roboto; }
        </style>
      </head>
      <body>
        <my-element></my-element>
      </body>
    </html>

    您也可以使用 :host CSS伪类从其自己的模板内部设置主体样式:

    static get styles() {
      return css`
        :host {
          font-family: Roboto;
        }
      `;
    }
    render() {
      return html`
        <p>Uses Roboto</p>
      `;
    }

    注意:元素类型选择器比 :host 伪类选择器有更高的优先级

    为自定义元素标签设置的样式将会覆盖通过 :host :host() 设置的

    <style>
      my-element { font-family: Courier; }
    </style>
    <my-element></my-element>
    class MyElement extends LitElement {
      static get styles() { 
        return css`:host { font-family: Roboto; }`
      }
      render() {
        return html`<p>Will use courier</p>`;
      }
    }

    8.2 CSS自定义属性

    所有的CSS自定义属性(--custom-property-name)都可被继承,你可以通过可配置的方式将外部样式用在你的组件上

    以下组件将其背景色设置为CSS变量。使用--my-background值(如果可用),否则默认为黄色:

    class MyElement extends LitElement {
      static get styles() { 
        return css`
          :host { 
            background-color: var(--my-background, yellow); 
          }
        `;
      }
      render() {
        return html`<p>Hello world</p>`;
      }
    }

    使用该组件的使用者可以用my-element标签作为CSS选择器来设置--my-background的值:

    <style>
      my-element {
        --my-background: rgb(67, 156, 144);
      }
    </style>
    <my-element></my-element>

    --my-background可根据my-element的每个实例进行配置:

    <style>
      my-element {
        --my-background: rgb(67, 156, 144);
      }
      my-element.stuff {
        --my-background: #111111;
      }
    </style>
    <my-element></my-element>
    <my-element class="stuff"></my-element>

    如果组件使用者具有现有的应用程序主题,则他们可以轻松地设置组件的可配置属性以使用主题属性:

    <html>
      <head>
        <title>lit-element code sample</title>
        <script type="module" src="./my-element.js"></script>
        <style>
          html { --themeColor1: rgb(67, 156, 144); }
          my-element {
            --myBackground: var(--themeColor1);
            --myColor: rgb(156, 67, 152);
          }
        </style>
      </head>
      <body>
        <my-element></my-element>
      </body>
    </html>
    import { LitElement, html, css } from 'lit-element';
    
    class MyElement extends LitElement {
      static get styles() {
        return css`
          :host { 
            background-color: var(--myBackground, yellow);
            color: var(--myColor, black);
            padding: var(--myPadding, 8px);
          }
        `;
      }
      render() {
        return html`<p>Hello world</p>`;
      }
    }
    customElements.define('my-element', MyElement);

    一个简单的示例主题

    index.html

    <html>
      <head>
        <script type="module" src="./my-element.js"></script>
        <title>lit-element code sample</title>
        <style>
          html {
            --theme-primary: green;
            --theme-secondary: aliceblue;
            --theme-warning: red;
            --theme-font-family: Roboto;
          }
          my-element { 
            --my-element-text-color: var(--theme-primary); 
            --my-element-background-color: var(--theme-secondary); 
            --my-element-font-family: var(--theme-font-family);
          } 
          .warning {
            --my-element-text-color: var(--theme-warning); 
          }
        </style>
      </head>
      <body>
        <my-element></my-element>
        <my-element class="warning"></my-element>
      </body>
    </html>

    my-element.js

    import { LitElement, html, css } from 'lit-element';
    
    class MyElement extends LitElement {
      static get styles() { 
        return css`
          :host { 
            display: block;
            color: var(--my-element-text-color, black); 
            background: var(--my-element-background-color, white);  
            font-family: var(--my-element-font-family, Roboto);
          }
          :host([hidden]) {
            display: none;
          }
        `;
      }
      render() {
        return html`<div>Hello World</div>`;
      }
    }
    customElements.define('my-element', MyElement);
  • 相关阅读:
    LR学习笔记6-常用术语
    LR学习笔记5-LR界面分析3
    LR学习笔记4-LR界面分析2
    LR学习笔记3-LR界面分析1
    Maven快速导出maven工程的依赖包
    Python3 将txt数据转换成列表,进行排序,筛选
    iOS OC环信实时语音切换听筒免提听不到声音报错:AVAudioSessionErrorCodeBadParam
    iOS voip电话和sip软电话 --网络电话
    远程(离线)推送自定义推送声音,友盟、极光
    Swift3.0 自定义tableView复用cell 的写法,与CollectionViewCell的不同,数据model
  • 原文地址:https://www.cnblogs.com/jixiaohua/p/11974197.html
Copyright © 2011-2022 走看看