簡體   English   中英

LitElement:在小型 Web 組件中創建許多自定義樣式規則與幾個動態規則時的最佳實踐(或最佳性能)?

[英]LitElement: best practise (or best performance) when creating many custom style rules vs a couple of dynamic rules inside a tiny web component?

所以我正在開發一個非常小的 web 組件,作為更大設計系統的一部分。

我對 Web Components 的使用有點陌生,但我知道這個特定的 Web 組件可以在單個布局中多次使用。

這個 web 組件控制在傳入它的任何子組件周圍放置多少垂直空間。

該組件的解剖結構非常簡單:

import { LitElement, html, css, unsafeCSS, property, customElement } from 'lit-element';

export const spacingAmounts = {
  'x-small': css`4px`,
  'small': css`8px`,
  'medium': css`12px`,
  'large': css`16px`,
  'x-large': css`20px`,
  '2x-large': css`30px`,
  '3x-large': css`40px`,
  '4x-large': css`60px`,
  '5x-large': css`90px`,
  '6x-large': css`120px`,
};

const createSpacingStyleRules = (direction: 'top' | 'bottom') => {
  return Object.keys(spacingAmounts).map(s => {
    const amount = spacingAmounts[s];
    return css`
      :host([${unsafeCSS(direction)}="${unsafeCSS(s)}"]) {
        margin-${unsafeCSS(direction)}: ${unsafeCSS(amount)};
      }
    `;
  });
};

@customElement('gu-vertical-space')
export class GuVerticalSpace extends LitElement {
  @property() top: string;
  @property() bottom: string;

  static get styles() {
    const styles = [
      css`
        :host {
          display: block;
        }
      `,
      // ----------------------------------------------------------
      // @TODO:
      // test if it's better performance wise to either:
      //
      // 1 -  generate a verbose list of static styles for
      //      each instance of gu-vertical-space
      //  or
      // 2 -  generate a tiny amount of styles on the fly, 
      //      based on property inputs...
      // ----------------------------------------------------------
      // ...createSpacingStyleRules('top'),
      // ...createSpacingStyleRules('bottom'),
    ];
    return styles;
  }

  render() {
    const styles = [];
    if (this.top) {
      styles.push(css`
        :host([top="${unsafeCSS(this.top)}"]) {
          margin-top: ${spacingAmounts[this.top]}
        }
      `);
    }
    if (this.bottom) {
      styles.push(css`
        :host([bottom="${unsafeCSS(this.bottom)}"]) {
          margin-bottom: ${spacingAmounts[this.bottom]}
        }
      `);
    }
    return html`
      <style>${styles}</style>
      <slot></slot>
    `;
  }
}


這里有兩種方法可以將預定義的邊距量映射到 Web 組件主機的頂部或底部。

當前活躍的方法只是在渲染函數內動態生成一個<style>塊,其中包含任何邊距量,由“頂部”或“底部”輸入屬性決定。

我正在考慮的另一種方法(盡管在 atm 中被注釋掉了) - 是靜態生成大量樣式規則 - 從而避免需要在 render() 函數中生成任何動態樣式的東西,這可能是一個反模式 - 如果我正確理解了lit-element 文檔

也許我缺少一種更優雅的方法? 我傾向於當前的方法,只是因為它更容易理解 - 但對其他人的想法感到好奇!

正如 Alan 所建議的,這個問題的一個更簡單的解決方案是使用 css-variables。

基本上,只需在 connect() 生命周期事件中將輸入邊距量映射為 css 變量(或者,如果您認為道具在初始渲染后會發生變化,則進行渲染) - 並稱它為一天!

static get styles() {
  return css`
    :host {
      display: block;
      margin-top: var(--margin-top);
      margin-bottom: var(--margin-bottom);
    }
  `;
}

connectedCallback() {
  super.connectedCallback();
  this.style.setProperty(
    '--margin-top',
    this.top
      ? spacingAmounts[this.top]
      : 'unset'
  );
  this.style.setProperty(
    '--margin-bottom',
    this.bottom
      ? spacingAmounts[this.bottom]
      : 'unset'
  );
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM