# @xstate/vue
@xstate/vue package (opens new window) 包含将 XState (opens new window) 与 Vue (opens new window) 结合使用的实用程序。
¥The @xstate/vue package (opens new window) contains utilities for using XState (opens new window) with Vue (opens new window).
[[目录]]
¥
Vue 2 注意:
如果你使用的是 Vue 2.x,请参阅 Vue 秘诀;如果你想使用 Vue Composition API,请使用 xstate-vue2
包 (opens new window)。
¥If you're using Vue 2.x, please see the Vue recipe instead, or use the xstate-vue2
package (opens new window) if you want to use the Vue Composition API.
# 快速开始
¥Quick Start
安装
xstate
和@xstate/vue
:¥Install
xstate
and@xstate/vue
:
npm i xstate @xstate/vue
通过 CDN
¥Via CDN
<script src="https://unpkg.com/@xstate/vue/dist/xstate-vue.min.js"></script>
通过使用全局变量 XStateVue
¥By using the global variable XStateVue
导入
useMachine
合成函数:¥Import the
useMachine
composition function:
<script setup>
import { useMachine } from '@xstate/vue';
import { createMachine } from 'xstate';
const toggleMachine = createMachine({
id: 'toggle',
initial: 'inactive',
states: {
inactive: {
on: { TOGGLE: 'active' }
},
active: {
on: { TOGGLE: 'inactive' }
}
}
});
const { state, send } = useMachine(toggleMachine);
</script>
<template>
<button @click="send('TOGGLE')">
{{
state.value === 'inactive'
? 'Click to activate'
: 'Active! Click to deactivate'
}}
</button>
</template>
# API
# useMachine(machine, options?)
vue 组合函数 (opens new window) 解释给定的 machine
并启动在组件的生命周期内运行的服务。
¥A Vue composition function (opens new window) that interprets the given machine
and starts a service that runs for the lifetime of the component.
参数
¥Arguments
machine
- 一个 XState 机器 (opens new window)。¥
machine
- An XState machine (opens new window).options
(可选) - 解释器选项 (opens new window) 或以下机器配置选项之一:guards
、actions
、actors
、delays
、immediate
、context
或state
。¥
options
(optional) - Interpreter options (opens new window) OR one of the following Machine Config options:guards
,actions
,actors
,delays
,immediate
,context
, orstate
.
返回 { state, send, service}
:
¥Returns { state, send, service}
:
state
- 将机器的当前状态表示为 XStateState
对象。¥
state
- Represents the current state of the machine as an XStateState
object.send
- 将事件发送到正在运行的服务的函数。¥
send
- A function that sends events to the running service.service
- 创建的服务。¥
service
- The created service.
# useActor(actor, getSnapshot)
提供对现有 actor (opens new window) 的访问的 vue 组合函数 (opens new window)。
¥A Vue composition function (opens new window) that provides access to an existing actor (opens new window).
从 0.5.0 开始
¥Since 0.5.0
参数
¥Arguments
actor
- 一个类似 actor 的对象,包含.send(...)
和.subscribe(...)
方法。¥
actor
- an actor-like object that contains.send(...)
and.subscribe(...)
methods.getSnapshot
- 一个应该从actor
返回最新发出值的函数。¥
getSnapshot
- a function that should return the latest emitted value from theactor
.默认尝试从
actor.getSnapshot()
获取快照,如果不存在则返回undefined
。¥Defaults to attempting to get the snapshot from
actor.getSnapshot()
, or returningundefined
if that does not exist.
import { useActor } from '@xstate/vue';
const props = defineProps(['someSpawnedActor']);
const { state, send } = useActor(props.someSpawnedActor);
要订阅 actor 上的更改,同时保留 props 或其他反应变量的反应性,可以使用 Vue 的 computed (opens new window)。
¥To subscribe to changes on the an actor whilst retaining reactivity from props or another reactive variable, Vue's computed (opens new window) can be used.
const { state, send } = useActor(computed(() => props.someSpawnedActor));
# useInterpret(machine, options?, observer?)
vue 组合函数 (opens new window) 返回从 machine
和 options
创建的 service
(如果指定)。它还设置了对 service
和 observer
的订阅(如果提供)。
¥A Vue composition function (opens new window) that returns the service
created from the machine
with the options
, if specified. It also sets up a subscription to the service
with the observer
, if provided.
从 0.5.0 开始
¥Since 0.5.0
参数
¥Arguments
machine
- XState 机器 (opens new window) 或延迟返回机器的函数。¥
machine
- An XState machine (opens new window) or a function that lazily returns a machine.options
(可选) - 解释器选项 (opens new window) 和/或以下任何机器配置选项:guards
、actions
、services
、delays
、immediate
、context
、state
。¥
options
(optional) - Interpreter options (opens new window) and/or any of the following machine config options:guards
,actions
,services
,delays
,immediate
,context
,state
.observer
(可选) - 监听状态更新的观察者或监听器:¥
observer
(optional) - an observer or listener that listens to state updates:观察员(例如
{ next: (state) => {/* ... */} }
)¥an observer (e.g.,
{ next: (state) => {/* ... */} }
)或监听器(例如,
(state) => {/* ... */}
)¥or a listener (e.g.,
(state) => {/* ... */}
)
import { useInterpret } from '@xstate/vue';
import { someMachine } from '../path/to/someMachine';
const service = useInterpret(someMachine);
使用选项+监听器:
¥With options + listener:
import { useInterpret } from '@xstate/vue';
import { someMachine } from '../path/to/someMachine';
const service = useInterpret(
someMachine,
{
actions: {
/* ... */
}
},
(state) => {
// subscribes to state changes
console.log(state.value);
}
);
# useSelector(actor, selector, compare?, getSnapshot?)
vue 组合函数 (opens new window) 从 actor
的快照返回选定的值,例如服务。仅当所选值发生更改(由可选的 compare
函数确定)时,此钩子才会导致重新渲染。
¥A Vue composition function (opens new window) that returns the selected value from the snapshot of an actor
, such as a service. This hook will only cause a rerender if the selected value changes, as determined by the optional compare
function.
从 0.6.0 开始
¥Since 0.6.0
参数
¥Arguments
actor
- 包含.send(...)
和.subscribe(...)
方法的服务或类似参与者的对象。¥
actor
- a service or an actor-like object that contains.send(...)
and.subscribe(...)
methods.selector
- 一个函数,它将角色的 "当前状态"(快照)作为参数并返回所需的选定值。¥
selector
- a function that takes in an actor's "current state" (snapshot) as an argument and returns the desired selected value.compare
(可选) - 确定当前选择的值是否与先前选择的值相同的函数。¥
compare
(optional) - a function that determines if the current selected value is the same as the previous selected value.getSnapshot
(可选) - 一个应该从actor
返回最新发出值的函数。¥
getSnapshot
(optional) - a function that should return the latest emitted value from theactor
.默认尝试获取
actor.state
,如果不存在则返回undefined
。会自动从服务中提取状态。¥Defaults to attempting to get the
actor.state
, or returningundefined
if that does not exist. Will automatically pull the state from services.
import { useSelector } from '@xstate/vue';
const props = defineProps(['service']);
const selectCount = (state) => state.context.count;
const count = useSelector(props.service, selectCount);
具有 compare
功能:
¥With compare
function:
import { useSelector } from '@xstate/vue';
const props = defineProps(['service']);
const selectUser = (state) => state.context.user;
const compareUser = (prevUser, nextUser) => prevUser.id === nextUser.id;
const user = useSelector(props.service, selectUser, compareUser);
对于 useInterpret(...)
:
¥With useInterpret(...)
:
import { useInterpret, useSelector } from '@xstate/vue';
import { someMachine } from '../path/to/someMachine';
const selectCount = (state) => state.context.count;
const service = useInterpret(someMachine);
const count = useSelector(service, selectCount);
# 配置机器
¥Configuring Machines
可以通过将机器选项作为 useMachine(machine, options)
的第二个参数传递来配置现有机器。
¥Existing machines can be configured by passing the machine options as the 2nd argument of useMachine(machine, options)
.
示例:'fetchData'
服务和 'notifySuccess'
操作都是可配置的:
¥Example: the 'fetchData'
service and 'notifySuccess'
action are both configurable:
<script setup>
import { assign, createMachine } from 'xstate';
import { useMachine } from '@xstate/vue';
const fetchMachine = createMachine({
id: 'fetch',
initial: 'idle',
context: {
data: undefined,
error: undefined
},
states: {
idle: {
on: { FETCH: 'loading' }
},
loading: {
invoke: {
src: 'fetchData',
onDone: {
target: 'success',
actions: assign({
data: (_context, event) => event.data
})
},
onError: {
target: 'failure',
actions: assign({
error: (_context, event) => event.data
})
}
}
},
success: {
entry: 'notifySuccess',
type: 'final'
},
failure: {
on: {
RETRY: 'loading'
}
}
}
});
const props = defineProps({
onResolve: {
type: Function,
default: () => {}
}
});
const { state, send } = useMachine(fetchMachine, {
actions: {
notifySuccess: (ctx) => props.onResolve(ctx.data)
},
services: {
fetchData: (_context, event) =>
fetch(`some/api/${event.query}`).then((res) => res.json())
}
});
</script>
<template>
<template v-if="state.value === 'idle'">
<button @click="send({ type: 'FETCH', query: 'something' })">
Search for something
</button>
</template>
<template v-else-if="state.value === 'loading'">
<div>Searching...</div>
</template>
<template v-else-if="state.value === 'success'">
<div>Success! {{ state.context.data }}</div>
</template>
<template v-else-if="state.value === 'failure'">
<p>{{ state.context.error.message }}</p>
<button @click="send('RETRY')">Retry</button>
</template>
</template>
# 匹配状态
¥Matching States
对于 hierarchical (opens new window) 和 parallel (opens new window) 机器,状态值将是对象,而不是字符串。在这种情况下,最好使用 state.matches(...)
(opens new window):
¥For hierarchical (opens new window) and parallel (opens new window) machines, the state values will be objects, not strings. In this case, it's better to use state.matches(...)
(opens new window):
<template>
<div>
<loader-idle v-if="state.matches('idle')" />
<loader-loading-user v-else-if="state.matches({ loading: 'user' })" />
<loader-loading-friends v-else-if="state.matches({ loading: 'friends' })" />
</div>
</template>
# 持续和再水化状态
¥Persisted and Rehydrated State
你可以通过 options.state
使用 useMachine(...)
保持并补充状态:
¥You can persist and rehydrate state with useMachine(...)
via options.state
:
<script setup>
// Get the persisted state config object from somewhere, e.g. localStorage
const persistedState = JSON.parse(
localStorage.getItem('some-persisted-state-key')
);
const { state, send } = useMachine(someMachine, {
state: persistedState
});
</script>
# 从 0.4.0 迁移
¥Migration from 0.4.0
对于使用
invoke
或spawn(...)
创建的生成 Actor,请使用useActor()
钩子而不是useService()
:¥For spawned actors created using
invoke
orspawn(...)
, use theuseActor()
hook instead ofuseService()
:-import { useService } from '@xstate/vue'; +import { useActor } from '@xstate/vue'; -const {state, send} = useService(someActor); +const {state, send} = useActor(someActor);