XState — очень полезная библиотека конечного автомата для внешнего интерфейса, но официальная документация на веб-сайте только на английском языке.Чтобы помочь большему количеству людей понять и увеличить опыт чтения, я перевел китайскую версию здесь.
- Адрес склада (Звездочка⭐ приветствуется):GitHub.com/частотное измерение/маленький камень…
- Адрес документа:made-frequency.github.io/absorb-tarter-docs…
Из-за моего ограниченного уровня и короткого периода перевода ошибки неизбежны, и читатели могут критиковать и исправлять меня.
Машины состояний JavaScript и диаграммы состояний
JavaScript и TypeScript для современной сетиКонечный автомата такжеДиаграмма состояний.
Все еще не знакомы с конечными автоматами и диаграммами состояний?Прочитайте нашу презентацию.
📑 ПодчинятьсяСпецификация SCXML
💬 вStately Discord Communityобщаться с нами
Мешок
- 🤖
xstate
- Конечный автомат и основная библиотека диаграмм состояний + интерпретатор -
🔬
@xstate/fsm
- Минимальная конечная автоматная библиотека -
📉
@xstate/graph
- Набор утилит обхода графика для XState -
⚛️
@xstate/react
- React Hooks и набор утилит для использования XState в приложениях React. -
💚
@xstate/vue
- Функция композиции Vue и набор утилит для использования XState в приложениях Vue. -
🎷
@xstate/svelte
- Набор утилит Svelte для использования XState в приложениях Svelte. -
✅
@xstate/test
- Утилита для тестирования на основе моделей (с использованием XState) -
🔍
@xstate/inspect
- Проверьте набор утилит для XState
шаблон
Начните с создания одного из этих шаблонов в CodeSandbox:
- XState Template- Без рамки
- XState + TypeScript Template- Без рамки
- XState + React Template
- XState + React + TypeScript Template
- XState + Vue Template
- XState + Vue 3 Template
- XState + Svelte Template
Очень быстро начать
npm install xstate
import { createMachine, interpret } from 'xstate';
// 无状态的状态机定义
// machine.transition(...) 是解释器使用的纯函数。
const toggleMachine = createMachine({
id: 'toggle',
initial: 'inactive',
states: {
inactive: {
on: {
TOGGLE: { target: 'active' }
}
},
active: {
on: {
TOGGLE: { target: 'inactive' }
}
}
}
});
// 具有内部状态的状态机实例
const toggleService = interpret(toggleMachine)
.onTransition((state) => console.log(state.value))
.start();
// => 'inactive'
toggleService.send({ type: 'TOGGLE' });
// => 'active'
toggleService.send({ type: 'TOGGLE' });
// => 'inactive'
Пример обещания
📉 на stately.ai/vizПосмотреть визуализацию на
import { createMachine, interpret, assign } from 'xstate';
const fetchMachine = createMachine({
id: 'Dog API',
initial: 'idle',
context: {
dog: null
},
states: {
idle: {
on: {
FETCH: { target: 'loading' }
}
},
loading: {
invoke: {
id: 'fetchDog',
src: (context, event) =>
fetch('https://dog.ceo/api/breeds/image/random').then((data) =>
data.json()
),
onDone: {
target: 'resolved',
actions: assign({
dog: (_, event) => event.data
})
},
onError: {
target: 'rejected'
}
},
on: {
CANCEL: { target: 'idle' }
}
},
rejected: {
on: {
FETCH: { target: 'loading' }
}
},
resolved: {
type: 'final'
}
}
});
const dogService = interpret(fetchMachine)
.onTransition((state) => console.log(state.value))
.start();
dogService.send({ type: 'FETCH' });
- инструмент визуализации
- Зачем?
- Конечный автомат
- Иерархические (вложенные) конечные автоматы
- Параллельный конечный автомат
- историческое состояние
инструмент визуализации
Визуализируйте, моделируйте и делитесь своими диаграммами состояний в XState Viz!
Зачем?
Диаграмма состояний — это способ моделирования интерактивной системы с отслеживанием состояния. От одного компонента до всей логики приложения, это полезно для декларативного описания приложения.поведениеочень полезно.
читать📽 слайд-шоу (🎥 Видео) или ознакомьтесь с этими ресурсами, чтобы понять важность конечных автоматов и диаграмм состояний в пользовательском интерфейсе:
- Диаграмма состояний — визуальное представление сложной системы by David Harel
- Мир диаграмм состояний by Erik Mogensen
- чистый интерфейс by Guillermo Rauch
- Чистый пользовательский интерфейс by Adam Solove
- Spectrum — Сообщество диаграмм состояний(Для особых проблем с XState используйтеОбсуждение на GitHub)
Конечный автомат
import { createMachine } from 'xstate';
const lightMachine = createMachine({
id: 'light',
initial: 'green',
states: {
green: {
on: {
TIMER: { target: 'yellow' }
}
},
yellow: {
on: {
TIMER: { target: 'red' }
}
},
red: {
on: {
TIMER: { target: 'green' }
}
}
}
});
const currentState = 'green';
const nextState = lightMachine.transition(currentState, { type: 'TIMER' })
.value;
// => 'yellow'
Иерархические (вложенные) конечные автоматы
import { createMachine } from 'xstate';
const pedestrianStates = {
initial: 'walk',
states: {
walk: {
on: {
PED_TIMER: { target: 'wait' }
}
},
wait: {
on: {
PED_TIMER: { target: 'stop' }
}
},
stop: {}
}
};
const lightMachine = createMachine({
id: 'light',
initial: 'green',
states: {
green: {
on: {
TIMER: { target: 'yellow' }
}
},
yellow: {
on: {
TIMER: { target: 'red' }
}
},
red: {
on: {
TIMER: { target: 'green' }
},
...pedestrianStates
}
}
});
const currentState = 'yellow';
const nextState = lightMachine.transition(currentState, { type: 'TIMER' })
.value;
// => {
// red: 'walk'
// }
lightMachine.transition('red.walk', { type: 'PED_TIMER' }).value;
// => {
// red: 'wait'
// }
Обозначение объекта для иерархических состояний:
// ...
const waitState = lightMachine.transition(
{ red: 'walk' },
{ type: 'PED_TIMER' }
).value;
// => { red: 'wait' }
lightMachine.transition(waitState, { type: 'PED_TIMER' }).value;
// => { red: 'stop' }
lightMachine.transition({ red: 'stop' }, { type: 'TIMER' }).value;
// => 'green'
Параллельный конечный автомат
import { createMachine } from 'xstate';
const wordMachine = createMachine({
id: 'word',
type: 'parallel',
states: {
bold: {
initial: 'off',
states: {
on: {
on: {
TOGGLE_BOLD: { target: 'off' }
}
},
off: {
on: {
TOGGLE_BOLD: { target: 'on' }
}
}
}
},
underline: {
initial: 'off',
states: {
on: {
on: {
TOGGLE_UNDERLINE: { target: 'off' }
}
},
off: {
on: {
TOGGLE_UNDERLINE: { target: 'on' }
}
}
}
},
italics: {
initial: 'off',
states: {
on: {
on: {
TOGGLE_ITALICS: { target: 'off' }
}
},
off: {
on: {
TOGGLE_ITALICS: { target: 'on' }
}
}
}
},
list: {
initial: 'none',
states: {
none: {
on: {
BULLETS: { target: 'bullets' },
NUMBERS: { target: 'numbers' }
}
},
bullets: {
on: {
NONE: { target: 'none' },
NUMBERS: { target: 'numbers' }
}
},
numbers: {
on: {
BULLETS: { target: 'bullets' },
NONE: { target: 'none' }
}
}
}
}
}
});
const boldState = wordMachine.transition('bold.off', { type: 'TOGGLE_BOLD' })
.value;
// {
// bold: 'on',
// italics: 'off',
// underline: 'off',
// list: 'none'
// }
const nextState = wordMachine.transition(
{
bold: 'off',
italics: 'off',
underline: 'on',
list: 'bullets'
},
{ type: 'TOGGLE_ITALICS' }
).value;
// {
// bold: 'off',
// italics: 'on',
// underline: 'on',
// list: 'bullets'
// }
историческое состояние
import { createMachine } from 'xstate';
const paymentMachine = createMachine({
id: 'payment',
initial: 'method',
states: {
method: {
initial: 'cash',
states: {
cash: {
on: {
SWITCH_CHECK: { target: 'check' }
}
},
check: {
on: {
SWITCH_CASH: { target: 'cash' }
}
},
hist: { type: 'history' }
},
on: {
NEXT: { target: 'review' }
}
},
review: {
on: {
PREVIOUS: { target: 'method.hist' }
}
}
}
});
const checkState = paymentMachine.transition('method.cash', {
type: 'SWITCH_CHECK'
});
// => State {
// value: { method: 'check' },
// history: State { ... }
// }
const reviewState = paymentMachine.transition(checkState, { type: 'NEXT' });
// => State {
// value: 'review',
// history: State { ... }
// }
const previousState = paymentMachine.transition(reviewState, {
type: 'PREVIOUS'
}).value;
// => { method: 'check' }