教學
本指南將逐步說明如何建構一個簡單的「計時器」元件。如果您不熟悉虛擬 DOM,請嘗試完整的 Preact 教學。
:information_desk_person: 本指南假設您已完成 入門 文件,並已成功設定您的工具。如果不是,請從 Vite 開始。
Hello World
開箱即用,您在任何 Preact 程式碼庫中都會看到的兩個函式是 h()
和 render()
。h()
函式用於將 JSX 轉換為 Preact 可理解的結構。但它也可以直接使用,而無需任何 JSX
// With JSX
const App = <h1>Hello World!</h1>;
// ...the same without JSX
const App = h('h1', null, 'Hello World');
這本身並不會做任何事情,我們需要一種方法將 Hello-World 應用程式注入 DOM。為此,我們使用 render()
函式。
import { render } from 'preact';
const App = <h1>Hello World!</h1>;
// Inject our app into the DOM
render(App, document.getElementById('app'));
在 REPL 中執行恭喜,您已建立您的第一個 Preact 應用程式!
互動式 Hello World
呈現文字是一個開始,但我們希望讓我們的應用程式更具互動性。我們希望在資料變更時更新它。:star2
我們的最終目標是有一個應用程式,讓使用者可以在提交表單時輸入名稱並顯示它。為此,我們需要一個可以儲存我們提交內容的地方。這正是 元件 發揮作用的地方。
因此,讓我們將現有的 App 轉換為 元件
import { h, render, Component } from 'preact';
class App extends Component {
render() {
return <h1>Hello, world!</h1>;
}
}
render(<App />, document.getElementById("app"));
在 REPL 中執行您會注意到,我們在頂部新增了一個新的 Component
匯入,並且我們將 App
轉換為一個類別。這本身沒有用,但它是我們下一步要做的前身。為了讓事情更令人興奮,我們將新增一個帶有文字輸入和提交按鈕的表單。
import { h, render, Component } from 'preact';
class App extends Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<form>
<input type="text" />
<button type="submit">Update</button>
</form>
</div>
);
}
}
render(<App />, document.getElementById("app"));
在 REPL 中執行現在我們來聊聊!它開始看起來像一個真正的應用程式了!我們仍然需要讓它具有互動性。請記住,我們希望將 "Hello world!"
變更為 "Hello, [userinput]!"
,因此我們需要一種方法來知道目前的輸入值。
我們將它儲存在我們元件的一個稱為 state
的特殊屬性中。它很特別,因為當它透過 setState
方法更新時,Preact 不僅會更新狀態,還會為此元件排程一個呈現要求。一旦處理了請求,我們的元件將以更新的狀態重新呈現。
最後,我們需要透過設定 value
並將事件處理常式附加到 input
事件,將新的狀態附加到我們的輸入。
import { h, render, Component } from 'preact';
class App extends Component {
// Initialise our state. For now we only store the input value
state = { value: '' }
onInput = ev => {
// This will schedule a state update. Once updated the component
// will automatically re-render itself.
this.setState({ value: ev.currentTarget.value });
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<form>
<input type="text" value={this.state.value} onInput={this.onInput} />
<button type="submit">Update</button>
</form>
</div>
);
}
}
render(<App />, document.getElementById("app"));
在 REPL 中執行此時,從使用者的角度來看,應用程式不應有太大變化,但我們將在下一個步驟中將所有部分組合在一起。
我們將以類似於我們剛剛對輸入所做的方式,將處理常式新增到 <form>
的 submit
事件。不同之處在於,它會寫入我們 state
的另一個屬性,稱為 name
。然後,我們換掉標題,並在那裡插入我們的 state.name
值。
import { h, render, Component } from 'preact';
class App extends Component {
// Add `name` to the initial state
state = { value: '', name: 'world' }
onInput = ev => {
this.setState({ value: ev.currentTarget.value });
}
// Add a submit handler that updates the `name` with the latest input value
onSubmit = ev => {
// Prevent default browser behavior (aka don't submit the form here)
ev.preventDefault();
this.setState({ name: this.state.value });
}
render() {
return (
<div>
<h1>Hello, {this.state.name}!</h1>
<form onSubmit={this.onSubmit}>
<input type="text" value={this.state.value} onInput={this.onInput} />
<button type="submit">Update</button>
</form>
</div>
);
}
}
render(<App />, document.getElementById("app"));
在 REPL 中執行完成!我們現在可以輸入自訂名稱,按一下「更新」,我們的標題就會出現新名稱。
時鐘元件
我們寫了第一個元件,讓我們多練習一點。這次我們來建一個時鐘。
import { h, render, Component } from 'preact';
class Clock extends Component {
render() {
let time = new Date().toLocaleTimeString();
return <span>{time}</span>;
}
}
render(<Clock />, document.getElementById("app"));
在 REPL 中執行好,這很容易!問題是時間沒有改變。它凍結在我們呈現時鐘元件的那一刻。
因此,我們希望在元件新增到 DOM 後啟動 1 秒計時器,並在移除時停止計時器。我們將建立計時器,並在 componentDidMount
中儲存對它的參考,並在 componentWillUnmount
中停止計時器。在每次計時器滴答聲中,我們將使用新的時間值更新元件的 state
物件。這樣做會自動重新呈現元件。
import { h, render, Component } from 'preact';
class Clock extends Component {
state = { time: Date.now() };
// Called whenever our component is created
componentDidMount() {
// update time every second
this.timer = setInterval(() => {
this.setState({ time: Date.now() });
}, 1000);
}
// Called just before our component will be destroyed
componentWillUnmount() {
// stop when not renderable
clearInterval(this.timer);
}
render() {
let time = new Date(this.state.time).toLocaleTimeString();
return <span>{time}</span>;
}
}
render(<Clock />, document.getElementById("app"));
在 REPL 中執行我們又做到了!現在我們有一個 滴答作響的時鐘!