Svelte: сделать компонент реактивным для переменной (перерисовка)

Я хочу повторно визуализировать Body (мой тонкий компонент) всякий раз, когда view.current изменяется, чтобы он отображал соответствующий вид / компонент .svelte:

App.svelte

    <script>
    import Header from "./components/Header.svelte";
    import Footer from "./components/Footer.svelte";
    import Body from "./components/Body.svelte";

    import Login from "./views/Login.svelte";
    import Dashboard from "./views/Dashboard.svelte";

    import { view } from "./store";
</script>

<Header />
    <Body>
        {#if view.current === view.login}
            <Login />
        {:else if view.current === view.dashboard}
            <Dashboard />
        {/if}
    </Body>
<Footer />

В Body.svelte у меня просто есть слот, который стилизован

Body.svelte

    <div class="container">
    <div class="content">
        <slot></slot>
    </div>
</div>

<style>
    .container {
        padding: 1em;
        display: flex;
    }
    .content {
        margin: auto;
    }
</style>

В Login.svelte (и других компонентах svelte) я хочу изменить view.current:

Login.svelte

<script>
    import { view } from "../store";

    function handleLoginClick() {
        view.current = view.dashboard;
    }
</script>


<button type="button" on:click={handleLoginClick} class="btn btn-primary btn-lg login-btn">Login</button>

<style>
    .login-btn {
        display: block;
        margin: auto;
    }
</style>

store.js

    const user = {
    username: "",
    fullname: "",
    role: null,
    isLoggedIn: false
};

const view = {
    login: 1,
    dashboard: 2,
    current: 1
};

export {
    user,
    view
}

Значение view.current изменяется, как ожидалось, однако Body не обновляется / не обновляется. Таким образом, он всегда показывает login.svelte независимо от того, какой view.current был установлен. Есть ли быстрый и простой способ сделать тело реактивным для view.current, чтобы он перерисовывался, чтобы блок if / else в App.svelte переоценивался?


person Horst    schedule 26.10.2020    source источник
comment
Почему вы хотите, чтобы ваш Body компонент был повторно отрисован?   -  person Tholle    schedule 26.10.2020
comment
Когда для view.current установлено значение, допустим, я хочу отобразить материал в login.svelte, когда он настроен на панель управления, я хочу отобразить dashboard.svelte и так далее.   -  person Horst    schedule 26.10.2020
comment
это view изящный магазин?   -  person Stephane Vanraes    schedule 26.10.2020
comment
Нет, это просто файл js. Я также пытался просмотреть svelte.store, но он ведет себя точно так же. Я отредактировал сообщение и добавил содержимое store.js.   -  person Horst    schedule 26.10.2020
comment
Попробовать $: currentView = view.current; и использовать currentView в разметке? Примечание: я могу ошибаться, я еще не на 100% доволен Svelte.   -  person sp00m    schedule 26.10.2020
comment
К сожалению, это не работает - такое же поведение. : /   -  person Horst    schedule 26.10.2020


Ответы (1)


Импорт такой обычной переменной в компонент создает локальную копию указанной переменной. view, на который вы ссылаетесь в логине, не используется совместно с тем в приложении, поэтому изменения там не отражаются.

Svelte-способ разделения такого состояния между компонентами заключается в использовании store.

В вашей настройке это будет означать, что вы сначала определяете представление как магазин:

import { writable } from 'svelte/store'

const view = writable({
    login: 1,
    dashboard: 2,
    current: 1
});

В самих компонентах вы должны добавить к магазину префикс $

<script>
    function handleLoginClick() {
        $view.current = $view.dashboard;
    }
</script>
{#if $view.current === $view.login}
    <Login />
{:else if $view.current === $view.dashboard}
    <Dashboard />
{/if}
person Stephane Vanraes    schedule 26.10.2020
comment
Спасибо, это помогло. Не знал, что создает его локальную копию. - person Horst; 26.10.2020