JavaScript Micro-Framework لبناء تطبيقات الويب الواحدة
قم بتنزيل إصدارات CJS أو ESM أو UMD أو التثبيت عبر NPM:
npm install @ryanmorr/avalonAvalon هو حل الكل في واحد لإدارة الحالة والتوجيه ووجهات النظر لتطبيقات الويب:
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 ، وإجراء عمليات ASYNC ، وإرسال الإجراءات الأخرى ، والطفرات الالتزام ، وما إلى ذلك.
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 بشكل أفضل ، حدد معلمة ثانية لحل المكالمة (واختياريا معلمة ثالثة لرفض مكالمة) كجزء من توقيع وظيفة رد الاتصال. سيؤدي إرسال إجراء غير متزامن إلى إرجاع الوعد تلقائيًا. إليك مثال على كيفية تنفيذ إجراء غير متزامن لجلب البيانات من الخادم:
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) تعمل الطرق تمامًا مثل الإجراءات ، باستثناء أنها تستجيب أيضًا للتغييرات في مسار URL ، مثل أحداث النقر النقر التي يتم تشغيلها للمستخدم ، والمكالمات البرمجية إلى الأساليب navigate وإعادة redirect ، والانتقال إلى الأمام والخلف في مكدس تاريخ الجلسة. يجب تعريف المسار مع مائلة للأمام القيادة:
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 الحالي بشكل افتراضي. إرجاع قيمة الإرجاع لوظيفة الاتصال/المسار أو الوعد إذا كان إجراء/مسار غير متزامن.
// 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" ، العقد المفتاح للاختلاف في قائمة فعالة ، والمكونات الوظيفية عديمة الجنسية:
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' ) ;
} ) ; هذا المشروع مكرس للمجال العام كما هو موضح من قبل Unisense.