モジュラーハイパーアプリ-パート7


NOTE: this article series is superceded by

ようこそモジュラーハイパーアプリ上の私のシリーズの最後の部分に.私たちがこれまで行ったものを要約します、そして、いくつかの最終的な反射でサインをする前に、絵を完成してください.

回収する

見解
ビューの再利用可能な部分は、ビューまたはビューコンポーネントと呼ばれる関数として分割できます.ビューは、ビューのモデルを呼び出すオブジェクトを使用して必要な値とアクションを提供します.

原始変換
同じ静脈では、再利用可能な論理のビットは、原始的な変換の形で動作から抜け出すことができます.値をとり、完全な値ではなく新しい値を返します.

ドメイン
私たちは“ドメイン”の概念を提起した-地域/機能/あなたの残りの部分から分離することについて考えを意味するアプリケーションの側面.あるドメインに関する全てのロジックは、モジュール内で収集することを意味します.

モデル
モジュールはいくつかのビューと購読コンポーネントを持つことができます.同じドメインに属しているので、ほぼ同じモデルが必要です.これは、モジュールのすべてのビューとサブスクリプションのコンポーネントの1つの共通モデル形式を持つことを意味します.

ワイヤードアクション/モデル
アクションとモデル定義をそれぞれのドメインのモジュールに移動させるには、私が呼び出している関数で動的に定義する必要がありますwire .
アクションでwire 機能はどのように特定の値で動作するかを知るgettersetter , 引数として与えられます.wire 現在の状態を指定して、モジュールのビューのモデルを返す関数を返します.

アプリケーションモジュール
モジュールの動作が動作する値はしばしば複雑です.したがって、モジュールは私が呼んだ値初期化子もエクスポートしなければなりませんinit .
initプラスすべてのアクションとビュー(およびサブスクリプション)を含むモジュールは、スタンドアロンアプリケーションとして実行することができますので、“app modules”と呼ぶ.

他のユーザーへの
エーwire また、引数としてマップされた変換をとります.wire 他の引数として渡すためにモデル関数の他にマップされた変換を返すこともできますwire このように、モジュールは、より複雑なアプリケーションを形成するために一緒に配線することができます.

モジュールからモジュールを作る
しかし、アプリだけではない!モジュールを接続して他のモジュールを作ることもできます.
import * as foo from './foo.js'
import * as bar from './bar.js'

export const init = () => ({
    myfoo: foo.init()
    mybar: bar.init()     
}

export const wire = ({getter, setter}) => {

    const myfoo = foo.wire({
        getter: state => getter(state).myfoo,
        setter: (state, myfoo) => setter(state, {
            ...getter(state),
            myfoo,
        }),
        onSnap: bar.crackle,
    })

    const mybar = bar.wire({
        getter: state => getter(state).mybar,
        setter: (state, mybar) => setter(state. {
            ...getter(state),
            mybar,
        }),
    })

    return {
        pop: foo.pop,
        model:  state => ({
            myfoo: myfoo.model(state),
            mybar: mybar.model(state),
        })
    }
}

export const view = (model) => h('div', {}, [
    h('p', {}, [ text('Foo:'), foo.view(model.myfoo) ]),
    h('p', {}, [ text('Bar:'), bar.view(model.mybar) ]),
])
このように、アプリケーションはツリーアプリケーションモジュールとして構成することができます.いくつかの定期的な振舞いを持つボタンのように、多くを繰り返す小さなものでさえ、一度定義されて、多くの場所で再利用されることができました.

ダイナミックインスタンス
私たちが写真を完成するために加えなければならないもう1つのものがあります:いくつかのモジュールの値の複数のインスタンスが州にあるならば、我々は始めから彼らを知りませんか?
例えば:to do doリストのタスク項目どのように、我々は我々がまだ知らないタスクのためにゲッターとセッターを定義することができましたか?このようにgettersとsettersをパラメータ化できます:
// this is task-list.js

import * as task from './task.js'

const tasks = task.wire({
    getter: (state, id) => state.tasks[id],
    setter: (state, todo, id) => ({
        ...state,
        tasks: {...state.tasks, [id]: todo}
    }),
})
The id パラメータは、タスクの特定のインスタンスを参照します.
アクションtask.js を取得する必要がありますid ペイロードに渡すためにgetter and setter .
//this is task.js

export const wire = ({getter, setter}) => {

    const SetText = (state, {id, text}) => setter(
        state,
        {...getter(state, id), text},
        id
    )
    //...
アクションを得る唯一の方法id ペイロードとしては、モデル関数を使用します.
//this is task.js

export const wire = ({getter, setter}) => {

    return {
        model: (state, id) => ({
            ...getter(state, id),
            SetText: (_, event) =>
                [SetText, {id, text: event.target.value}],
            //...
        })
        //...
    }
}
//...        
The task-list.js モデルは現在、それぞれのタスクのためのサブモデルを作成することができますが発生するたびに、状態の更新:
//this is task-list.js

//...

const model = (state) => ({
    //...
    tasks: Object.keys(state.tasks).map(id =>    
        tasks.model(state, id)
    )
})

//...
id 数字または文字列である必要はありません.動的インスタンスの全ツリーを通してパスを表現する複雑なオブジェクトである可能性があります.動的なリストに動的なリストを持つこともできるように!

ついに!
そして、ここで、我々は最終的に、シリーズの終わりにです!おめでとう、よくすべての方法をそれを貼り付けるために行わ!
これは、我々は最終的にどのように大規模または複雑な-自己完結型、管理可能なモジュールで構成することができますが、個々に開発した後、任意のアプリケーションを参照してください、この点に長いと抽象的な旅されており、後で組み合わせた.

閉鎖思考
そのような構造は、あなたが反応を持っているか、または質問を乞うVue Virus Lungと似ています:なぜ、単に反応またはVueを使用しないでください?結局のところ、私は提示したこのアプリのモジュールのパターンは、かなりすべてのgetter ssetter sstateid s.
私はあなたの特定の状況で使用する正しいフレームワークを伝えることを想定しないでしょうが、HyperAppのケースを作るのを許します
まず最初に、私はあなたが必要とするならば、モジュール化をすることができた方法を示すために、このシリーズを書きました.HyperAppはあなたにだけのテクニックとパターンを使用するにはそれを残します.

If you want to dig in to a really over-modular example, I threw everything I had at this multi-todo-list app


すべてがコンポーネントである必要があるより堅いフレームワークと対照的に.あなたはそれを作る前に各コンポーネントが何をすべきかを決定する必要があります.最初は簡単ですが、より多くのコンポーネントを追加すると、それらの間の状態を共有するより多くの畳み込みを取得-問題は、duduxやvuexのような中央の州の店の開発につながっている.コンポーネントと状態を調整するためのすべてのメカニズムが学ぶために自分のAPIと来る.どのように多くの時間をあなたが反応フック、redux佐賀、ET . Cを把握するためのドキュメントやチュートリアルを注ぐ過ごしましたか?そして、一緒に合う作品を作ること?
状態はグローバルであり、デフォルトで共有されます.あなたがそのようにするまで、何もカプセル化されません.APIは最小限で死んで簡単です-それはあなたが望むすべてのことをしないが、それはまた、途中で取得しません.あなたはJavaScriptのあなたの処分であなたのアプリケーションを構築するための完全な電源を持っています.あなたがバグを持っている場合は、それはあなたがJavaScriptの間違った、ハイパーアプリではない使用しているためです.
ここの例は、より簡潔で、いくつかのライブラリコードで読みやすいようにすることができます.しかし、それから、私は私の図書館コードを使う方法を説明していて、その背後にある考えを伝えていません.
私はあなたがあなたのスタイルに合うパターンとヘルパーを理解すると思います.彼らはおそらく私のとは違って見えるだろうし、それは素晴らしいです!あなたが何を得るに関係なく、私は願って、私がここに提示したアイデアが役立つと信じて!