花了三天時間,一起初淺的學習了如何將 Web Component 使用在前端的三大框架中。
今天我們再一起將主角拉回建立 Web Component 的軌道上。
前端開發上有許許多多的框架,而建立 Web Component 其實也有一套框架(這時是不是想說那句經典台詞:老子學不動了啊~~~)。
別擔心,相信學會各大框架的你,這一定是輕而易舉,舉一就能反三的框架。
那麼今天要介紹關於開發 Web Component 的框架就是 Lit
。
Lit is a simple library for building fast, lightweight web components.
At Lit's core is a boilerplate-killing component base class that provides reactive state, scoped styles, and a declarative template system that's tiny, fast and expressive.
-- from lit.dev
Lit 是由 Google 開發用來建立 Web Components 的輕量級框架。是基於原生的 Web Component 標準(Custom Elements
+ Shadow DOM
+ Template literals
)的一層封裝。
使用 Lit 開發的元件其實都是標準的 Web Component。從我們這系列文章最初的介紹,到前三篇的解說之下,你應該可以了解到 Web Component 是具有非常好的互通性。
因為瀏覽器原生支持,所以 Web Component 可以用在任何 HTML 的環境中,可以跟任何框架配合使用,也可以不需要框架。
就跟我們平時在開發網頁一樣,其實也是為了讓開發更有效率,降低程式碼的複雜度,能用更簡潔的語法來開發 Web Component(前面寫得那麼多篇文章,相信你可能也被複雜大量的程式碼給嚇到了)。
extends HTMLElement
來繼承 HTMLElement
的屬性及方法?Lit
時,我們需要繼承 LitElement
。ReactiveElement
,讓元件可以有屬性到畫面的反應更新。export class CounterBtn extends LitElement {}
customElements.define()
,@customElement
直接定義元件。export class CounterBtn extends HTMLElement { // 略... }
customElements.define('counter-btn', CounterBtn);
@customElement
:注意: @customElement 是裝飾器語法,需要經過編譯,像是
TypeScript
或Babel
才能運行。
@customElement('counter-btn')
export class CounterBtn extends LitElement { // 略... }
元件的 Shadow DOM:
由於我們已經繼承了 LitElement
所以不需要再像原生的寫法一樣使用 shadowRoot = this.attachShadow({ mode: 'open' })
,Lit 會自動啟用 Shadow DOM。
模板的寫入:
你是否還記得,之前都是使用 const template = document.createElement('template')
之後寫入 innerHTML
。
而在 Lit 中,你會需要建立一個 render()
的方法,並使用 html
寫入 template。
render() {
const template = document.createElement('template');
template.innerHTML = `<p>Hello Custom Element</p>`;
}
render(){
return html`<p>Hello Custom Element</p>`;
}
template.innerHTML
中,而 Lit 提供了 static styles = css
方法,定義在 class 中寫入樣式。static styles = css`
button {
padding: 0.5rem;
border-bottom: 1px solid #ccc;
display: flex;
justify-content: space-between;
align-items: center;
}
`;
在這篇文章,我希望實作一個 counter 的元件作為範例。
vite
建立一個前端專案,選擇 TypeScriptnpm create vite@latest lit-demo
npm install lit
tsconfig.json
加上規則,讓我們可以使用 lit 裝飾器"compilerOptions": {
//...略
"experimentalDecorators": true,
}
src/counter.ts
中引入 Lit 相關方法及屬性import { LitElement, html, css } from 'lit';
import { customElement } from 'lit/decorators.js';
@customElement('counter-btn')
export class CounterBtn extends LitElement {
// 定義樣式
static styles = css`
.counter-wrapper {
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
padding: 32px;
}
.counter {
display: flex;
align-items: center;
gap: 8px;
}
button {
padding: 0.5rem 1rem;
font-size: 1rem;
border: none;
border-radius: 4px;
cursor: pointer;
}
button.increment {
background-color: #e1d9d9;
}
button.decrement {
background-color: #c9b7b7;
}
button.reset {
background-color: #0d2b44;
color: white;
}
`
// 寫入模板相關內容
render() {
return html`
<div class="counter-wrapper">
<div class="counter">
<button class="decrement">-</button>
<span>Count:</span>
<button class="increment">+</button>
</div>
<button class="reset">Reset</button>
</div>
`
}
}
main.ts
中引入元件import './counter.ts'
const app = document.querySelector('#app')!;
// 建立一個 counter 元件
const counter = document.createElement('counter-btn');
app.appendChild(counter);
index.html
中引入 main.ts
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
npm run dev
跑起來看看元件是否有出現恭喜!使用 Lit 初步建立的元件就定義好囉~
那麼明天,我們再來說說關於屬性還有事件的傳遞吧 d(`・∀・)b !