标识 State 节点

:rocket: 快速参考

默认情况下,状态节点的 id 是其区分的完整路径。 你可以使用这个默认的 id 来指定一个状态节点:

  1. const lightMachine = createMachine({
  2. id: 'light',
  3. initial: 'green',
  4. states: {
  5. green: {
  6. // 默认 ID: 'light.green'
  7. on: {
  8. // 你可以按默认 ID 定位状态节点。
  9. // 这与 TIMER 相同:'yellow'
  10. TIMER: { target: '#light.yellow' }
  11. }
  12. },
  13. yellow: {
  14. on: {
  15. TIMER: { target: 'red' }
  16. }
  17. },
  18. red: {
  19. on: {
  20. TIMER: { target: 'green' }
  21. }
  22. }
  23. }
  24. });

相关目标

通过指定一个点('.')后跟它们的键,可以相对于它们的父节点来定位子状态节点:

```js {10-12} const optionsMachine = createMachine({ id: ‘options’, initial: ‘first’, states: { first: {}, second: {}, third: {} }, on: { SELECT_FIRST: { target: ‘.first’ }, // resolves to ‘options.first’ SELECT_SECOND: { target: ‘.second’ }, // ‘options.second’ SELECT_THIRD: { target: ‘.third’ } // ‘options.third’ } });

  1. 默认情况下,相对目标是 [内部转换](./transitions.md#internal-transitions),这意味着父状态将 _不_ 退出并重新进入。 你可以通过指定 `internal: false` 来使相对目标外部转换:
  2. ```js {4}
  3. // ...
  4. on: {
  5. SELECT_FIRST: {
  6. target: { target: '.first' },
  7. internal: false // 外部转换,将退出/重新进入父状态节点
  8. }
  9. }

自定义 ID

可以通过唯一标识符而不是相对标识符来定位状态节点。 这可以简化复杂状态图的创建。

要为状态节点指定 ID,请提供唯一的字符串标识符作为其 id 属性,例如,id: 'greenLight'

要通过 ID 定位状态节点,请在其字符串 ID 前添加 # 符号,例如,TIMER: '#greenLight'

  1. const lightMachine = createMachine({
  2. id: 'light',
  3. initial: 'green',
  4. states: {
  5. green: {
  6. // 自定义 id
  7. id: 'greenLight',
  8. on: {
  9. // 目标状态节点通过其 ID
  10. TIMER: { target: '#yellowLight' }
  11. }
  12. },
  13. yellow: {
  14. id: 'yellowLight',
  15. on: {
  16. TIMER: { target: '#redLight' }
  17. }
  18. },
  19. red: {
  20. id: 'redLight',
  21. on: {
  22. // 相对目标仍然有效
  23. TIMER: { target: 'green' }
  24. }
  25. }
  26. }
  27. });

笔记:

  • 始终建议为根状态节点使用 ID。
  • 确保所有 ID 都是唯一的,以防止命名冲突。 这自然由自动生成的 ID 强制执行。

::: warning 不要将自定义标识符与相对标识符混合使用。 例如,如果上面的 red 状态节点有一个自定义的 "redLight" ID 和一个子 walking 状态节点,例如:

  1. // ...
  2. red: {
  3. id: 'redLight',
  4. initial: 'walking',
  5. states: {
  6. // ID 仍然解析为“light.red.walking”
  7. walking: {/* ... */},
  8. // ...
  9. }
  10. }
  11. // ...

那么你就不能通过 '#redLight.walking' 定位 'walking' 状态,因为它的 ID 被解析为 '#light.red.walking'。 以'#' 开头的目标将始终引用 '#[state node ID]'完全匹配。 :::

快速参考

默认自动生成 ID:

  1. const lightMachine = createMachine({
  2. id: 'light',
  3. initial: 'green',
  4. states: {
  5. // ID: "light.green"
  6. green: {
  7. /* ... */
  8. },
  9. // ID: "light.yellow"
  10. yellow: {
  11. /* ... */
  12. },
  13. // ID: "light.red"
  14. red: {
  15. /* ... */
  16. }
  17. }
  18. });

自定义 ID

  1. // ...
  2. states: {
  3. active: {
  4. id: 'custom-active', // can be any unique string
  5. // ...
  6. }
  7. }

通过 ID 定位到 state:

  1. // ...
  2. on: {
  3. EVENT: { target: '#light.yellow' }, // 目标到默认 ID
  4. ANOTHER_EVENT: { target: '#custom-id' } // 目标到自定义 ID
  5. }