Hyperappの簡単な紹介
Hyperapp は、宣言型Webアプリケーションの構築に使用される非常に小さいマイクロフレームワークです。 サイズはわずか1kBで、APIはReactに似ていますが、完璧ですよね?! Hyperappがどのように機能するかを示すために、小さなカウンターアプリを作成します。
新しいハイパープロジェクト
開始するには、新しいノードアプリケーションを作成し、hyperapp
をインストールします。 次に、parcelを使用してこのアプリケーションを提供します。
# New directory, here we call it `hyper` $ mkdir hyper && cd hyper # Initialise Node project $ npm init -y # Install Hyperapp $ npm i hyperapp # Create index.html and app.js $ touch index.html $ touch app.js # Install `parcel` globally $ npm i parcel -g # Serve our application in the browser $ parcel index.html
次に、hyperapp
コードを含むapp.js
を含む標準のindex.html
ページを作成できます。
<!DOCTYPE html> <html lang="en"> <head> <title>🎉 Hyperapp</title> </head> <body> <div id="app"></div> <script src="app.js"></script> </body> </html>
カウンターの構築
状態駆動型アプリケーションは、常に反例から始まります。 これにより、アプリケーション内でのデータの流れに慣れることができます。 いくつかのstate
を定義することから始めましょう:
app.js
const state = { count: 0 }
次に、そのstate
に基づいてview
を定義できます。 これは、標準のテンプレート構文を使用して表示できます。
app.js
// ... const view = state => ( <div> <h1>{state.count}</h1> </div> );
最後に、これをDOM内の特定の要素にアタッチできます。 app
のid
を使用して、これをdiv
に追加することを選択しました。
app.js
// ... const el = document.getElementById('app'); const main = app(state, {}, view, el);
シンプルなアプリは次のようになります。
state
は不変であり、直接更新する必要がないため、actions
を追加して、state
を次のように操作できます。
app.js
// ... const actions = { increment: () => state => ({ count: (state.count += 1) }), decrement: () => state => ({ count: (state.count -= 1) }) };
これは、main
およびview
の内部に配線して、actions
にアクセスできるようにすることができます。
app.js
// ... const view = (state, actions) => ( <div> <h1>{state.count}</h1> <button onclick={() => actions.increment()}>Increment</button> <button onclick={() => actions.decrement()}>Decrement</button> </div> ); const main = app(state, actions, view, el);
ここで、[インクリメント]または[デクリメント]を選択すると、合計カウントが増減します。
これを特定の数だけ上下させたい場合はどうなりますか? この機能を追加しましょう。
まず、state
オブジェクトに新しいアイテムを追加できます。 これをdiff
と呼ぶことにしました。これは、加算と減算の違いを表すためです。
const state = { count: 1, diff: 1 };
次に、actions
を更新して、これに基づいてインクリメントまたはデクリメントできます。
const actions = { updateCount: diff => state => ({ diff: diff }), increment: diff => state => ({ count: (state.count += Number(diff)) }), decrement: diff => state => ({ count: (state.count -= Number(diff)) }) };
そして最後に、view
を更新できます。
const view = (state, actions) => ( <div> <input value={state.diff} oninput={e => actions.updateCount(e.target.value)} /> <h1>{state.count}</h1> <button onclick={() => actions.increment(state.diff)}>Increment</button> <button onclick={() => actions.decrement(state.diff)}>Decrement</button> </div> );
これで、入力データを利用して状態を更新できるようになりました。
コンポーネント
Hyperappプロジェクトからコンポーネントを作成する方法を見てみましょう。 Counter
コンポーネントを作成し、これをページとルートの中に埋め込む方法を見ていきます。
components/Count.js
に新しいファイルを作成し、props
からcount
を取り込むカウンターを追加します。
Count.js
import { h } from 'hyperapp'; const Count = ({ count }) => <h1>{count}</h1>; export default Count;
次に、app.js
の内部でimport
を実行できます。
app.js
import Count from './components/Count'; // ...
次に、count
を小道具としてview
内のCount
に渡すことができます。
app.js
// ... const view = () => (state, actions) => ( <div> <Count count={state.count} /> <button onclick={actions.increment}>Increment</button> <button onclick={actions.decrement}>Decrement</button> </div> );
また、state
とactions
をcount
の単純なincrement
とdecrement
に更新しました。
const state = { count: 0 }; const actions = { increment: () => ({ count: (state.count += 1) }), decrement: () => ({ count: (state.count -= 1) }) };
ルーティング
Hyperapp内のルーティングを利用することもできます。 次のようにルーターパッケージ(@hyperapp/router
)をインストールしましょう。
$ npm i @hyperapp/router
次に、app.js
内のルーティングコンポーネントをimport
できます。
app.js
import { Link, Route, location } from '@hyperapp/router';
これで、Home
とBlog
の2つの異なるページを作成できます。
app.js
// ... const Home = () => (state, actions) => ( <div> <Count count={state.count} /> <button onclick={actions.increment}>Increment</button> <button onclick={actions.decrement}>Decrement</button> </div> ); const Blog = () => <h1>Blog!</h1>;
Home
ページには以前の反例が含まれており、Blog
ページは単なるテキストです。 これらをRoute
とLink
として、view
の内部に割り当てましょう。
app.js
// ... const view = state => ( <div> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/blog">Blog</Link> </li> </ul> <Route path="/" render={Home} /> <Route path="/blog" render={Blog} /> </div> );
次に、History APIに基づいているため、ルーターにlocation
へのアクセスを許可する必要があります。 state
とactions
に以下を追加します。
app.js
const state = { location: location.state, count: 0 }; const actions = { location: location.actions, increment: () => state => ({ count: (state.count += 1) }), decrement: diff => state => ({ count: (state.count -= 1) }) };
最後に、location
自体をサブスクライブする必要があります。
app.js
// ... const unsubscribe = location.subscribe(main.location);
これで、アプリケーション内のさまざまなページから選択できるようになりました。
ルーティング例の完全なコードは次のとおりです。
app.js
import { h, app } from 'hyperapp'; import { Link, location } from '@hyperapp/router'; import Count from './components/Count'; const state = { location: location.state, count: 0 }; const actions = { location: location.actions, increment: () => state => ({ count: (state.count += 1) }), decrement: diff => state => ({ count: (state.count -= 1) }) }; const Home = () => (state, actions) => ( <div> <Count count={state.count} /> <button onclick={actions.increment}>Increment</button> <button onclick={actions.decrement}>Decrement</button> </div> ); const Blog = () => <h1>Blog!</h1>; const view = state => ( <div> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/blog">Blog</Link> </li> </ul> <Route path="/" render={Home} /> <Route path="/blog" render={Blog} /> </div> ); const main = app(state, actions, view, document.body); const unsubscribe = location.subscribe(main.location);
結論
これで、あなたはレースに出かける必要があります! 🏇また、 Hyperapp2.0にも注目してください。まもなくリリースされる予定です。