Обновление функции хранилища Svelte

#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.7

4. Еще раз спасибо за второй пример. Я думаю, что могу попытаться использовать хранилище как нечто, что не похоже на то, что вы говорите. Возможно, я упускаю из виду суть поведения хранилища / реакции, нужно поработать над этим. Спасибо

Ответ №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 будет обновляться

вот пример реализации