是否可以在不对当前状态使用条件语句的情况下使用状态机?
Is it posible to use a State Machine without using Conditional Statements on the Current State?
我想使用当前状态映射到当前屏幕的状态机。我正在使用 svelte with xstate.
以字符串为类型的示例:
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' }
}
}
});
如何使用 svelte 组件而不是字符串来做同样的事情?
而不是 <p>{$toggleService.value}</p>
这样的东西 <$toggleService.value />
编辑:我尝试过的:
- 创建大厅和登录 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.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 (/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
我不能代表 xstate 部分,但最后一个片段肯定不起作用。您不能像这样动态声明标签。但是你可以为此使用特殊的 <svelte:component>
元素:
<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} />
感谢 dummdidumm 帮助解决了 svelte 部分的问题。
如何在不写条件语句的情况下一起使用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 }),
}
}
});
我想使用当前状态映射到当前屏幕的状态机。我正在使用 svelte with xstate.
以字符串为类型的示例:
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' }
}
}
});
如何使用 svelte 组件而不是字符串来做同样的事情?
而不是 <p>{$toggleService.value}</p>
这样的东西 <$toggleService.value />
编辑:我尝试过的:
- 创建大厅和登录 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.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 (/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
我不能代表 xstate 部分,但最后一个片段肯定不起作用。您不能像这样动态声明标签。但是你可以为此使用特殊的 <svelte:component>
元素:
<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} />
感谢 dummdidumm 帮助解决了 svelte 部分的问题。
如何在不写条件语句的情况下一起使用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 }),
}
}
});