Я не прав?
Да. Не вини себя, хотя, твои ожидания кажутся мне только логичными. Но это не совсем так.
Как правило, если где-то в коде компонента есть префиксная переменная $
, тогда это должно быть хранилище , и оно будет подписываться сразу при создании компонента и отписываться при уничтожении компонента.
Небольшое исключение из этого правила было введено совсем недавно (с этим PR ). Я позволю вам пройти по тропе вниз по кроличьей норе, если вы хотите узнать всю дискуссию. Суть в том, что теперь подписка на магазин должна быть магазином или nulli sh (то есть null
или undefined
- см. этот комментарий ).
Это означает, что теперь можно при желании взломать ваш путь к ожидаемому вами поведению. Мы возвращаемся к этому.
Почему $ store подписывается, если canSubscribe имеет значение false?
Поскольку магазины подписаны сразу. Насколько я понимаю из обсуждения вышеизложенных вопросов, оно относится к производительности (размеру байта) и здравому смыслу (быстро и явно проваливается, если кто-то пытается подписаться на то, что не является магазином). Имеет смысл для меня.
Теперь вернемся к вопросу, который вы не задавали: как подписаться только когда / если необходимо? Поместите хранилище в переменную с автоподпиской только при необходимости и оставьте значение nulli sh в противном случае.
Не делайте:
$: started && $store
Сделайте это вместо:
$: proxyStore = started ? store : null
$: console.log($proxyStore)
Полный пример ( REPL ):
import { writable } from 'svelte/store'
const state1 = { subscribed: 0, unsubscribed: 0 }
const store1 = writable(42, () => {
state1.subscribed++
return () => {
state1.unsubscribed++
}
})
const state2 = { subscribed: 0, unsubscribed: 0 }
const store2 = writable(43, () => {
state2.subscribed++
return () => {
state2.unsubscribed++
}
})
let started = false
$: started && $store1
$: targetStore = started ? store2 : null
$: $targetStore
started = {started}
store1 = {$store1} {JSON.stringify(state1)}
store2 = {$targetStore} {JSON.stringify(state2)}
{начато =! Началось}}> {началось? «Пуск»: «Стоп»}