【问题标题】:Is it posible to use a State Machine without using Conditional Statements on the Current State?是否可以在不使用当前状态的条件语句的情况下使用状态机?
【发布时间】:2021-11-01 18:53:47
【问题描述】:

我想使用当前状态映射到当前屏幕的状态机。我正在使用sveltexstate
以字符串为类型的示例:
App.svelte

<script>
    import { interpret } from "xstate";
    import { toggleMachine } from "./machine";

    const toggleService = interpret(toggleMachine).start();
</script>

<button on:click={() => toggleService.send("TOGGLE")}>
    <p>{$toggleService.value}</p>
</button>

machine.js

import { createMachine } from 'xstate';

// This machine is completely decoupled from Svelte
export const toggleMachine = createMachine({
    id: 'toggle',
    initial: 'LOGIN',
    states: {
        LOBBY: {
            on: { TOGGLE: 'LOGIN' }
        },
        LOGIN: {
            on: { TOGGLE: 'LOBBY' }
        }
    }
});

如何用细长的组件而不是字符串来做同样的事情?
而不是&lt;p&gt;{$toggleService.value}&lt;/p&gt; 这样的&lt;$toggleService.value /&gt;

编辑:我尝试了什么:

  • 创建 Lobby 和 Login svelte 组件 Login.svelte
<script lang="ts">
</script>

<main>
    <h1>Login</h1>
</main>

<style>
</style>

Lobby.svelte

<script lang="ts">
</script>

<main>
    <h1>Lobby</h1>
</main>

<style>
</style>

  • 在 machine.js 中使用它们
import { createMachine } from 'xstate';
import Login from './Login.svelte'
import Lobby from './Lobby.svelte'
// This machine is completely decoupled from Svelte
export const toggleMachine = createMachine({
    id: 'toggle',
    initial: Login,
    states: {
        Login: {
            on: { TOGGLE: Lobby }
        },
        Lobby: {
            on: { TOGGLE: Login }
        }
    }
});
  • 在 App.svelte 中使用状态机 App.svelte
<script>
    import { interpret } from "xstate";
    import { toggleMachine } from "./machine";

    const toggleService = interpret(toggleMachine).start();
</script>

<button on:click={() => toggleService.send("TOGGLE")}>
    <$toggleService.value />
</button>

我得到错误:

[!] (plugin svelte) ParseError: Expected valid tag name
src/App.svelte
 7: 
 8: <button on:click={() => toggleService.send("TOGGLE")}>
 9:   <$toggleService.value />
       ^
10: </button>
ParseError: Expected valid tag name
    at error (/home/walde/projects/svelte/xstate/node_modules/svelte/src/compiler/utils/error.ts:25:16)
    at Parser$1.error (/home/walde/projects/svelte/xstate/node_modules/svelte/src/compiler/parse/index.ts:101:3)
    at read_tag_name (/home/walde/projects/svelte/xstate/node_modules/svelte/src/compiler/parse/state/tag.ts:267:10)
    at tag (/home/walde/projects/svelte/xstate/node_modules/svelte/src/compiler/parse/state/tag.ts:77:15)
    at new Parser$1 (/home/walde/projects/svelte/xstate/node_modules/svelte/src/compiler/parse/index.ts:53:12)
    at parse (/home/walde/projects/svelte/xstate/node_modules/svelte/src/compiler/parse/index.ts:218:17)
    at compile (/home/walde/projects/svelte/xstate/node_modules/svelte/src/compiler/compile/index.ts:93:14)
    at Object.transform (/home/walde/projects/svelte/xstate/node_modules/rollup-plugin-svelte/index.js:111:21)
    at /home/walde/projects/svelte/xstate/node_modules/rollup/dist/shared/rollup.js:20218:25

【问题讨论】:

    标签: javascript user-interface svelte state-machine xstate


    【解决方案1】:

    我不能代表 xstate 部分,但最后一个 sn-p 肯定不起作用。您不能像这样动态声明标签。但是您可以为此使用特殊的&lt;svelte:component&gt; 元素:

    <script>
        import { interpret } from "xstate";
        import { toggleMachine } from "./machine";
    
        const toggleService = interpret(toggleMachine).start();
    </script>
    
    <button on:click={() => toggleService.send("TOGGLE")}>
        Toggle me
    </button>
    <svelte:component this={$toggleService.value} />
    

    文档:https://svelte.dev/docs#svelte_component

    【讨论】:

      【解决方案2】:

      感谢 dummdidumm 帮助解决纤细部分的问题。

      svelte 和 xstate 不写条件语句的问题的完整解决方法是:

      • 将组件绑定到状态机的上下文
      <svelte:component this={$toggleService.context.component} />
      
      • 将进入时的状态机上下文更改为新状态,使其与当前状态匹配。
              Login: {
                  on: { TOGGLE: "Lobby" },
                  entry: assign({ component: (ctx) => ctx.component = Login }),
              }
      

      完整的工作示例:
      App.svelte

      <script>
          import { interpret } from "xstate";
          import { toggleMachine } from "./machine";
          const toggleService = interpret(toggleMachine).start();
      </script>
      
      <button on:click={() => toggleService.send("TOGGLE")}>
          {$toggleService.value}
      </button>
      <svelte:component this={$toggleService.context.component} />
      

      Lobby.svelte

      <script lang="ts">
      </script>
      <main>
          <h1>SVELTE Lobby</h1>
      </main>
      <style>
      </style>
      

      Login.svelte

      <script lang="ts">
      </script>
      <main>
          <h1>SVELTE Login</h1>
      </main>
      <style>
      </style>
      

      machine.js

      import { createMachine, assign } from 'xstate';
      import Login from './Login.svelte'
      import Lobby from './Lobby.svelte'
      export const toggleMachine = createMachine({
          id: 'toggle',
          initial: "Login",
          context: {
              component: Lobby
          },
          states: {
              Login: {
                  on: { TOGGLE: "Lobby" },
                  entry: assign({ component: (ctx) => ctx.component = Login }),
              },
              Lobby: {
                  on: { TOGGLE: "Login" },
                  entry: assign({ component: (ctx) => ctx.component = Lobby }),
              }
          }
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-27
        • 1970-01-01
        • 1970-01-01
        • 2021-03-09
        • 2013-01-11
        • 1970-01-01
        相关资源
        最近更新 更多