Svelte 5 методов реактивного хранилища

Приведенный ниже код работает так, как должен, я просто пытаюсь лучше понять, почему.

Насколько getCurrentElementметод TestState реактивен без использования $derived()? Являются ли методы хранилища, использующие состояние, реактивными по умолчанию?

Я использую [email protected]

test-store.svelte.ts

import { getContext, setContext } from 'svelte';

class TestState {
  elements = [
    {
      id: 'hghxt',
      name: 'Give',
    },
    {
      id: 'vhtl9',
      name: 'Connection',
    },
    {
      id: '5n0t0',
      name: 'Take notice',
    },
    {
      id: 'xlfba',
      name: 'Keep learning',
    },
    {
      id: '1f3z2',
      name: 'Be active',
    },
  ];

  #currentElementId = $state<string>();
  
  getCurrentElement() {
    return this.elements.find(element => element.id === this.#currentElementId);
  }

  setCurrentElement(id: string) {
    if (!this.elements.some(element => element.id === id)) return;

    this.#currentElementId = id;
  }
}

const TEST_STORE_KEY = Symbol('TEST_STORE');

export function setTestState() {
  return setContext(TEST_STORE_KEY, new TestState());
}

export function getTestState() {
  return getContext<ReturnType<typeof setTestState>>(TEST_STORE_KEY);
}

TestComponent.svelte

<script lang = "ts">
  import { getTestState } from '$lib/stores/test-store.svelte';

  // initialised at +page.svelte
  const testState = getTestState();
</script>

{#each testState.elements as { name, id }}
  <button 
    class:bg-yellow = {testState.getCurrentElement()?.id === id} 
    onclick = {() => testState.setCurrentElement(id)}>
    {name}
  </button>
{/each}
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В своем «HTML-коде» вы называете testState.getCurrentElement(). Когда вы это сделаете, Svelte заметит, от каких реактивных переменных зависит этот вызов. В getCurrentElement() вы получаете доступ к this.#currentElementId, поэтому Svelte знает, что эту часть «HTML-кода» необходимо повторно отобразить/обновить, когда this.#currentElementId присвоено новое значение.

Вам нужно использовать $derived() только тогда, когда вы хотите автоматически вычислить новое значение, как только реактивная переменная изменит значение, и здесь это не тот случай, поэтому я не вижу здесь никакого смысла использовать $derived().


@JackTempleman, возможно, мы называем вещи по-разному, но такого понятия, как реактивная функция, не существует, по крайней мере, в моем словаре. У нас есть только реактивные переменные/выражения, которые можно создать с помощью некоторых рун, например $state(). Если одна из ваших функций использует реактивную переменную/выражение, то сама эта функция не является реактивной; это просто функция, которая использует реактивные переменные/выражения. Только создание такой функции не приведет к самостоятельным пересчетам. Но если вы вызываете/используете такую ​​функцию в некоторых местах, где Svelte отслеживает реактивность (например, в HTML-коде компонента или в некоторых рунах), тогда Svelte узнает о реактивных переменных/выражениях, которые использует функция, и Svelte вызовет функция снова в будущем, когда эти реактивные переменные/выражения изменят значение.

Понятно. Таким образом, Svelte распознает, когда функция использует состояние, добавляет ее в качестве зависимости и повторно запускает функцию при обновлении ее зависимостей. Отличный ДХ.

Jack Templeman 15.08.2024 10:56

Делает ли это, по сути, любую функцию, использующую состояние, обратным вызовом $derived.by?

Jack Templeman 15.08.2024 10:59

Нет, я так не думаю. Если бы это было так, то весь код, который вы пишете, был бы реактивным, а это не так: код JS верхнего уровня в компоненте не является реактивным, и его нужно поместить в какую-то руну для повторного запуска всякий раз, когда назначается используемая им реактивная переменная. новое значение. Svelte реагирует только в некоторых местах (например, в HTML-коде и в некоторых рунах).

Peppe L-G 15.08.2024 12:37

Но этот вопрос предполагает, что если это функция и она просто использует руну, она становится реактивной? Оба этих утверждения являются реактивными, когда selectedElementId определяется с использованием $state. const selectedElementFunction = () => elements.find(ele => ele.id === selectedElementId); и const selectedElementDerived = $derived(elements.find(ele => ele.id === selectedElementId));

Jack Templeman 15.08.2024 15:22

@PeppeL-G: $derived ленив, он пересчитывает только при использовании (пример). Основная причина использования $derived — кэширование дорогостоящих вычислений.

brunnerh 15.08.2024 16:38

@JackTempleman, см. обновленный ответ. Хотя не уверен, что это прояснит ситуацию. И, как отметил @brunnerh, $derived() может повысить производительность.

Peppe L-G 15.08.2024 21:16

Возможно, это прояснит ситуацию: const selectedElementFunction = () => elements.find(ele => ele.id === selectedElementId); никогда не будет вызывать перерасчеты сам по себе. Это произойдет только в том случае, если вы вызовете его из своего HTML-кода или из руны (например, $derived). Если вы вызовете его на верхнем уровне JS в файле Svelte, он никогда не вызовет повторные вычисления из-за этого вызова.

Peppe L-G 15.08.2024 21:21

Другие вопросы по теме