JavaScriptシングルページWebアプリケーションを構築するためのマイクロフレームワーク
CJS、ESM、UMDバージョンをダウンロードするか、NPM経由でインストールします。
npm install @ryanmorr/avalonAvalonは、Webアプリの状態、ルーティング、およびビューを管理するためのオールインワンソリューションです。
import avalon from '@ryanmorr/avalon' ;
const app = avalon ( {
count : 0
} ) ;
app . mutation ( 'increment' , ( { count } ) => {
return {
count : count + 1
} ;
} ) ;
app . action ( 'handleClick' , ( { commit } ) => {
commit ( 'increment' ) ;
} ) ;
app . view ( parent , ( html , { count } , dispatch ) => html `
< div >
< p > Count: ${ count } </ p >
< button onclick = ${ dispatch ( 'handleClick' ) } > Increment </ button >
</ div >
` ) ;TODOMVCの例をご覧ください。
avalon(state?)プレーンキー/値オブジェクトとして初期状態を持つアプリケーションインスタンスを作成します。 titleプロパティは現在のドキュメントタイトルのために予約されており、変更を変更します。ドキュメントタイトルが自動的に更新されます。
const app = avalon ( {
title : 'Hello World' ,
foo : 1 ,
bar : 2
} ) ;mutation(name, callback)アプリケーション状態に統合される部分状態オブジェクトを返すことにより、状態を同期させる名前とコールバック関数を提供することにより、突然変異を定義します。
app . mutation ( 'foo' , ( state , payload ) => {
return {
foo : payload
} ;
} ) ;commit(name, payload?)その名前とオプションのペイロードを提供することにより、アプリケーション状態を更新するために突然変異を呼び出して、突然変異に起因する部分状態を返します。
app . mutation ( 'foo' , ( state , n ) => ( { foo : n + 10 } ) ) ;
app . commit ( 'foo' , 10 ) ; //=> {foo: 20}action(name, callback)DOMイベントリスナーに応答し、非同期操作を実行し、その他のアクションを派遣し、突然変異を派遣するなどの名前とコールバック関数を提供することにより、アクションを定義します。
app . action ( 'foo' , ( { state , params , event , dispatch , commit , navigate , redirect , emit } ) => {
/**
* state - the current state of the app
* params - key/value object provided to the dispatcher or null if not provided
* event - the event object of user triggered DOM events or null if not applicable
* commit - function for calling mutations
* dispatch - function for dispatching actions or routes
* navigate - function for navigating to a URL path and dispatching a route
* redirect - function for redirecting to a URL path and dispatching a route
* emit - function for emitting a custom event
*/
} ) ;Async操作をより適切にサポートするには、アクションコールバック関数の署名の一部として、コールを解決するための2番目のパラメーター(およびオプションで3番目のパラメーター)を定義します。非同期アクションを派遣すると、自動的に約束が返されます。サーバーからデータを取得するために非同期アクションを実装する方法の例は次のとおりです。
app . action ( 'load' , ( { params , commit } , resolve , reject ) => {
commit ( 'isLoading' , true ) ;
request ( '/get' , params ) . then ( ( data ) => {
commit ( 'isLoading' , false ) ;
commit ( 'setData' , data ) ;
resolve ( data ) ;
} ) . catch ( ( error ) => {
commit ( 'isLoading' , false ) ;
commit ( 'setError' , error ) ;
reject ( error ) ;
} ) ;
} ) ;
app . dispatch ( 'load' , { id : 'foo' } ) . then ( ( data ) => {
// Handle data
} ) . catch ( ( error ) => {
// Handle error
} ) ;route(path, callback)ルートはアクションとまったく同じように機能しますが、ユーザーがトリガーされたクリックイベントやフォームの提出物、ナビnavigateおよびredirectメソッドへのプログラムコール、セッション履歴スタックの前後に移動するなど、URLパスの変更にも応答します。ルートは、前方のスラッシュで定義する必要があります。
app . route ( '/' , ( { state , path , params , event , dispatch , commit , navigate , redirect , emit } ) => {
/**
* state - the current state of the app
* path - the URL path that matched the route
* params - key/value object extracted from a route's parameters or null if static path
* event - the event object of user triggered DOM events or null if not applicable
* commit - function for calling mutations
* dispatch - function for dispatching actions or routes
* navigate - function for navigating to a URL path and dispatching a route
* redirect - function for redirecting to a URL path and dispatching a route
* emit - function for emitting a custom event
*/
} ) ;ルートはパラメーター、オプションのパラメーター、およびワイルドカードをサポートします。
// Matches routes like "/a/b/c" and "/x/y/z"
app . route ( '/:foo/:bar/:baz' , ( { params : { foo , bar , baz } } ) => {
// Do something
} ) ;
// Matches routes like "/a/b" and "/a"
app . route ( '/:foo/:bar?' , ( { params : { foo , bar } } ) => {
// Do something
} ) ;
// Matches routes like "/", "/a", and "/a/b/c"
app . route ( '/*' , ( { params : { wildcard } } ) => {
// Do something
} ) ;dispatch(name?, params?)オプションのパラメーターまたはルートでアクションを発送します。引数が提供されていない場合、デフォルトで現在のURLパスが使用されます。 Asyncアクション/ルートの場合、アクション/ルートコールバック関数の返品値または約束を返します。
// Dispatch an action with parameters
app . dispatch ( 'foo' , { foo : 1 , bar : 2 } ) ;
// Dispatch the first matching route (parameters are extracted from the URL path)
app . dispatch ( '/foo/bar/baz' ) ;
// Dispatching an async action/route returns a promise
app . dispatch ( 'load' ) . then ( ( data ) => {
// Do something
} )view(element, callback)状態が変更されたときに、すぐにレンダリングされるビューを定義し、仮想DOMを介して自動的に更新されます。ビューコールバック関数は、タグ付きテンプレート、現在の状態、およびキー/値オブジェクトとしてオプションのパラメーターを持つDOMイベントリスナーの結果として、アクションとルートをディスパッチするための便利なディスパッチ関数を介して仮想DOMビルダーを提供されます。
app . view ( parentElement , ( html , state , dispatch ) => html `
< div >
< p > Name: ${ state . name } </ p >
< button onclick = ${ dispatch ( 'handleClick' , { foo : 1 , bar : 2 } ) } > Increment </ button >
</ div >
` ) ;ビューは、属性/プロパティ、文字列またはオブジェクトとしてのCSSスタイル、「on」のプレフィックスで示されるイベントリスナー、効率的なリストdiffのキー付きノード、およびステートレス機能コンポーネントで示されます。
const Item = ( html , props , dispatch ) => html `
< li key = ${ props . id } onclick = ${ dispatch ( 'handleClick' , { id : props . id } ) } >
${ props . children }
</ li >
` ;
app . view ( parentElement , ( html , state ) => html `
< ul class =" list " >
${ state . items . map ( ( item ) => html `
< ${ Item } id = ${ item . id } > ${ item . name } </ />
` ) }
</ ul >
` ) ;navigate(path)提供されたURLパスを使用して新しいエントリを履歴スタックに押し込み、最初のマッチングルートをディスパッチします。ルートコールバック関数の返品値またはそれが非同期ルートの場合は約束を返します。
app . route ( '/foo' , ( ) => 'bar' ) ;
app . path ( ) ; //=> "/"
history . length ; //=> 0
app . navigate ( '/foo' ) ; //=> "bar"
app . path ( ) ; //=> "/foo"
history . length ; //=> 1redirect(path)現在の履歴エントリを提供されたURLパスに置き換え、最初のマッチングルートをディスパッチします。ルートコールバック関数の返品値またはそれが非同期ルートの場合は約束を返します。
app . route ( '/foo' , ( ) => 'bar' ) ;
app . path ( ) ; //=> "/"
history . length ; //=> 0
app . redirect ( '/foo' ) ; //=> "bar"
app . path ( ) ; //=> "/foo"
history . length ; //=> 0on(name, callback)アプリケーションイベントを購読し、関数を返して、その特定のリスナーを削除します。
// Listen for state changes
app . on ( 'mutation' , ( name , nextState , prevState , partialState ) => {
// Do something
} ) ;
// Listen for when an action/route is dispatched
app . on ( 'dispatch' , ( type , state , name , params , event , returnValue ) => {
// Do something
} ) ;
// Listen for when the URL path changes
app . on ( 'pathchange' , ( path ) => {
// Do something
} ) ;
// Listen for when a view has been rendered
app . on ( 'render' , ( parentElement ) => {
// Do something
} ) ;
// Define your own custom event with parameters
const stop = app . on ( 'foo' , ( a , b , c , d ) => {
// Do something
} ) ;
// Stop listening for custom event
stop ( ) ;emit(name, ...args?)オプションの引数でカスタムイベントをトリガーします。
app . on ( 'foo' , ( a , b , c , d ) => {
// Do something
} ) ;
app . emit ( 'foo' , 1 , 2 , 3 , 4 ) ;state()現在の状態オブジェクトを取得します:
const app = avalon ( {
title : 'Hello World'
foo : 1 ,
bar : 2
} ) ;
app . state ( ) ; //=> {title: "Hello World", foo: 1, bar: 2}path()現在のURLパスを取得します:
app . navigate ( '/foo' ) ;
app . path ( ) ; //=> "/foo"use(plugin)アプリケーションインスタンスと現在の状態ですぐに呼び出されるコールバック関数を提供して、プラグインを追加します。プラグインコールバック関数の返品値を返します:
// A simple logging plugin
const log = app . use ( ( app , state ) => {
const events = [
'mutation' ,
'dispatch' ,
'pathchange' ,
'render'
] ;
events . forEach ( ( name ) => app . on ( name , console . log . bind ( console , name ) ) ) ;
return console . log . bind ( console , 'avalon' ) ;
} ) ; このプロジェクトは、Unlicenseで説明されているように、パブリックドメインに捧げられています。