我什么时候应该在 Svelte 定制商店中使用衍生产品?

BHO*_*OLT 10 svelte

我已经遵循了很棒的 Svelte 教程,但我无法理解何时应该derived在我的定制商店中使用。在此示例中,我创建了一个具有 3 个状态的游戏:

  • PRE_GAME
  • IN_GAME
  • POST_GAME

当我处于这些状态之一时,我想返回一个布尔检查,我认为最好在定制商店本身。

这是我当前的代码:

import { writable, derived } from 'svelte/store';

export const gamestate = (() {
  const { set, subscribe } = writable('PRE_GAME');

  return {
    subscribe,
    set
  };
})();

export const preGame = derived(gamestate, ($gamestate) => $gamestate === 'PRE_GAME');
export const inGame = derived(gamestate, ($gamestate) => $gamestate === 'IN_GAME');
export const postGame = derived(gamestate, ($gamestate) => $gamestate === 'POST_GAME');
Run Code Online (Sandbox Code Playgroud)

是否可以将派生方法移至商店,gamestate例如gamestate.preGame()?这在 Svelte 中有意义吗?然后我可以打电话$gameState并获取任何值,而且当我需要显式值时也返回布尔检查。

我希望能够检查内部值而不需要导出它的值。也许像下面这样,但它总是返回 false,因为它gamestate是一个可写对象。

export const createStore = (() {
  const { set, subscribe } = writable('PRE_GAME');

  return {
    subscribe,
    set,
    preGame: () => gamestate === 'PRE_GAME',
    inGame: () => gamestate === 'IN_GAME',
    postGame: () => gamestate === 'POST_GAME',
  };
})();
Run Code Online (Sandbox Code Playgroud)

我在这里误解了什么?

Ste*_*aes 10

您要做的是将订阅返回到自定义商店中的派生商店:

import { derived, writable } from 'svelte/store'

export const gameState = (() => {
  const store = writable('PRE_GAME')
  const store2 = derived(store, $store => ({
    preGame: $store === 'PRE_GAME',
    inGame: $store === 'IN_GAME',
    postGame: $store === 'POST_GAME'        
  }))
    
  return {
    set: store.set,
    subscribe: store2.subscribe
  }
})()
Run Code Online (Sandbox Code Playgroud)

现在,当您在 store 上执行此操作时,它将在storeset上设置值,然后store2将派生新值,订阅者将对这些更改做出反应:

<script>
  import { gameState } from "./store.js"
</script>

<button on:click="{() => $gameState='PRE_GAME'}">go PRE_GAME</button>
<button on:click="{() => $gameState='IN_GAME'}">go IN_GAME</button>
<button on:click="{() => $gameState='POST_GAME'}">go POST_GAME</button>

<br />

{#if $gameState.preGame}
    <span>PRE_GAME</span>
{/if}

{#if $gameState.inGame}
    <span>IN_GAME</span>
{/if}

{#if $gameState.postGame}
    <span>POST_GAME</span>
{/if}
Run Code Online (Sandbox Code Playgroud)

选择

您还可getters以为每个特定状态定义不同的:

import { derived, writable } from 'svelte/store'

export const gameState = (() => {
  const store = writable('PRE_GAME')
    const { set, subscribe } = store

  return {
    set,
    subscribe,
        get preGame() { return derived(store, $store => $store === 'PRE_GAME') },
        get inGame() { return derived(store, $store => $store === 'IN_GAME') },
        get postGame() { return derived(store, $store=> $store === 'POST_GAME') },
  }
})()
Run Code Online (Sandbox Code Playgroud)

现在唯一的问题是doing$gameState.preGame不存在,因为它试图从$gameState的内容中获取preGame道具,而doing或类似的语法是无效的。为了解决这个问题,你可以在需要的地方解构商店中的道具:gameState.$preGame

<script>
  import { gameState } from './store.js'
  const { preGame, inGame, postGame } = gameState
</script>

<span>Current State: {$gameState}</span>
{#if preGame}<span>PRE_GAME</span>{/if}
{#if inGame}<span>IN_GAME</span>{/if}
{#if postGame}<span>POST_GAME</span>{/if}
Run Code Online (Sandbox Code Playgroud)


Eti*_*nne 4

存储上的自定义方法用于改变状态(设置和更新),但存储通常只有一个 getter:状态。我认为你不希望事情变成这样。

\n

从这里开始,我看到三个解决方案:\xc2\xa0

\n
    \n
  • 将您的状态设为对象{ gameSate: 'PRE_GAME', isPreGame: true, isInGame: false, isPostGame:\xc2\xa0false },然后使用自定义更新函数。
  • \n
  • 像您一样使用派生存储(我认为在主存储中导入派生或使用没有意义get())。
  • \n
  • 在组件中进行计算,可能会制作一个专用组件。您的组件仍然是纯粹声明性的,唯一发生变化的东西仍然在商店中。
  • \n
\n

我会在纯粹的 DRYness:\xc2\xa0imports 和重复该子句之间做出决定。

\n