Tengo la siguiente tienda esbelta:
export type SessionStore = { session?: Session, sessionType?: SessionType, inputs: [] } La generación del campo de inputs cambiará dependiendo del tipo de sesión:
Tengo una tienda personalizada que genera el estado de la sesión en función de la acción del usuario:
function makeSessionStore() { const {subscribe, set, update} = writable(initialValue()); return { subscribe, createLocalSession: () => update(() => ({ session: {state: SessionState.RUNNING}, sessionType: SessionType.LOCAL, inputs: [] // <--- how to generate this based on the session type? })), createNetworkSession: () => createSession().then(session => update(() => ({ session, sessionType: SessionType.NETWORK, inputs: [] }))) reset: () => set(initialValue()) } }Mi pregunta: ¿Cómo puedo adjuntar una propiedad de tienda reactiva a la propiedad de entradas?
Así es, por ejemplo, cómo obtengo las entradas del teclado del usuario:
const keysPressed: Readable<string[]> = readable([], function(set) { let keys = []; const onKeydown = ({key}) => { if (keys.includes(key)) { return; } keys = [...keys, key]; set(keys); } const onKeyup = ({key}) => { if (!keys.includes(key)) { return; } keys = keys.filter(k => k !== key); set(keys); } document.addEventListener('keydown', onKeydown); document.addEventListener('keyup', onKeyup); return () => { document.removeEventListener('keydown', onKeydown); document.removeEventListener('keyup', onKeyup); } })Me gustaría que los componentes que usan las entradas desconozcan el cambio de estrategia detrás de escena, deberían poder usar las entradas de esta manera:
import {sessionStore} from './session'; console.log($sessionStore.inputs) // ['CONTROL', 'w']Terminé usando componentes ranurados en lugar de tiendas para este problema.
Idea básica: envuelva los componentes que dependen de la entrada en contenedores, que definen el tipo de entrada.
{#if !session} <h1>no session</h1> {:else if session.type === SessionType.LOCAL} <LocalSessionWrapper let:inputs={inputs}> <slot inputs={inputs}></slot> </LocalSessionWrapper> {:else} {#if session.state === SessionState.PENDING} <h3>waiting for other player...</h3> {:else if session.state === SessionState.CLOSED} <h3>game over!</h3> {:else if session.state === SessionState.RUNNING} <NetworkSessionWrapper let:inputs={inputs}> <slot inputs={inputs}></slot> </NetworkSessionWrapper> {:else } <h3>unknown game state</h3> {/if} {/if}Los componentes de envoltura usan tiendas para definir la fuente de entrada:
LocalSessionWrapper :
<script lang="ts"> import {localSessionInputs, Session} from "./game/session"; export let session: Session; </script> <slot inputs={$localSessionInputs}></slot>