#javascript #svelte #svelte-3 #svelte-store
#javascript #svelte #svelte-3 #хранилище svelte
Вопрос:
Документация хранилища Svelte показывает, что строка или целое число обновляются, но я не нашел ни одной динамической функции в хранилище.
Я не понимаю, как сделать getData
функцию доступной для записи, чтобы уведомить html об изменении.
В следующем примере я хотел бы b
, чтобы он отображался после updateKey
вызова функции.
Здесь вы найдете минимальный код на REPL: https://svelte.dev/repl/3c86bd48d5b5428daee514765c926e58?version=3.29.7
И тот же код здесь на случай, если REPL будет отключен:
App.svelte:
<script>
import { getData } from './store.js';
import { updateKey } from './store.js';
setTimeout(updateKey, 1000);
</script>
<h1>{getData()}!</h1>
store.js
import {setContext} from 'svelte';
import {writable} from 'svelte/store';
var data = {
'a': 'a',
'b': 'b'
};
var key = 'a';
export const getData = function() {
return data[key];
}
export const updateKey = () => {
key = 'b';
}
Цель состоит в том, чтобы работать с динамической функцией в хранилище.
Ответ №1:
Ну, я думаю, у вас все еще есть небольшая путаница в том, как все работает в Svelte… Не уверен, как лучше всего ответить на ваш вопрос, поэтому вот некоторый код для того, чего вы пытаетесь достичь, а также некоторые комментарии. Я надеюсь, что это поможет вам лучше понять, как все складывается в отношении магазинов.
App.svelte
<script>
import { onMount } from 'svelte'
import { key, data, updateKey } from './store.js'
onMount(() => {
// it's not safe to have an unchecked timer running -- problems would
// occur if the component is destroyed before the timeout has ellapsed,
// that's why we're using the `onMount` lifecycle function and its
// cleanup function here
const timeout = setTimeout(updateKey, 1000);
// this cleanup function is called when the component is destroyed
return () => {
clearTimeout(timeout)
}
})
// this will log the value of the `key` store each time it changes, using
// a reactive expression (a Sveltism)
$: console.log($key)
</script>
<!--
NOTE: we're using the $ prefix notation to access _the value_ of the store,
and not `data`, which would be _the store itself_ (an object with
subscribe, set, etc.)
-->
<h1>{$data}</h1>
store.js
import { writable, derived } from 'svelte/store'
const db = {
'a': 'a',
'b': 'b'
}
// a writable store with initial value 'a'
export const key = writable('a')
export const updateKey = () => {
// a writable store has a `set` method to change its value
key.set('b')
}
// you can use a derived store to compute derived values from
// the current value of other stores
//
// here, we're getting the value from the db when the value of
// the `key` store changes
export const data = derived([key], ([$key]) => db[$key])
Комментарии:
1. Спасибо за этот ответ. Это делает именно то, что я имел в виду, с отличными комментариями. Я воспользуюсь моментом, чтобы понять производное поведение.
2. Я обновил REPL: svelte.dev/repl/3c86bd48d5b5428daee514765c926e58?version = 3.29.7 Основной вопрос заключался в передаче параметра в функции хранилища. Возможно ли это?
3. Нет, это невозможно напрямую — вызовы функций никогда не реагируют. Что вы можете сделать, так это вызвать вашу функцию в реактивном выражении при изменении значения lang. Но IMO этот вызов функции действительно пытается навязать некоторый процедурный стиль, в котором более функциональный подход был бы гораздо более естественным для Svelte и, вероятно, в конечном итоге менее подвержен ошибкам. Для этого вызов вашей функции приведет к изменению значения
key
хранилища, доступного для записи, и результат будет получен из производного хранилища. Обновленный REPL для иллюстрации обоих подходов: svelte.dev/repl/7633dfdc70bb4eee80d0a87e4bd1a631?version= 3.29.74. Еще раз спасибо за второй пример. Я думаю, что могу попытаться использовать хранилище как нечто, что не похоже на то, что вы говорите. Возможно, я упускаю из виду суть поведения хранилища / реакции, нужно поработать над этим. Спасибо
Ответ №2:
если я правильно понял ваш вопрос, вы хотите иметь возможность изменять функцию (логику), которая выполняется, getData()
и вы хотите, чтобы для каждой функции изменялся html, который будет обновляться
для этого варианта использования вам нужно будет создать свой собственный пользовательский магазин
следующим образом в store.js
import { writable } from 'svelte/store';
// an object to hold our functions
const functions = {
"funcA": () => {
// do something
return "whatevedata for a"
},
"funcB": () => {
// do something
return "the data of b"
}
}
// this how to create a custom store, taken from svelte documentation
function createCustomStore(defaultValue) {
const { subscribe, set, update } = writable(defaultValue);
return {
subscribe,
//custom function change func where suppliedValue the value you input to the store
// set() is a default function for a store to change it's value
changeFunc: (suppliedValue) => set(functions[suppliedValue]),
reset: () => set(defaultValue)
};
}
export const getData = createCustomStore(() => "default");
export const updateKey = () => {
// this to update which function the store uses
getData.changeFunc("funcB")
}
в приложении.svelte
<script>
import { getData } from './store.js';
import { updateKey } from './store.js';
setTimeout(function() {
updateKey()
}, 1000);
</script>
<h1>{$getData()}</h1>
мы добавили $
to getData
, потому что это хранилище, которое содержит ссылки на функции, и ()
оно предназначено для выполнения любой функции, на которую ссылается getData
store. поскольку это хранилище при каждом изменении значения (изменении функции) getData
, html будет обновляться
вот пример реализации