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, выполнять асинхрологические операции, отправлять другие действия, мутации совершения и т. Д. Функции обратного вызова действия предоставляется объект соответствующих данных и функций удобства в качестве первого параметра:
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
*/
} ) ;Чтобы лучше поддерживать асинхронные операции, определите второй параметр для разрешения вызова (и, необязательно, третий параметр для отклонения вызова) как часть подписи функции обратного действия. Расследование асинхронного действия автоматически вернет обещание. Вот пример того, как вы можете реализовать асинхронное действие для получения данных с сервера:
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' ) ;
} ) ; Этот проект посвящен общественному доступу, как описано нелизостью.