Svelte — меню и меняющиеся url

Admin Svelte

Настраиваем меню в Svelte, подсвечиваем текущую страницу и создаем в адресной строке url к ссылкам.

Я уже строил меню на готовых решениях, вроде svelte-tabs. Здесь покажу как сделать его своими усилиями. Плюс добавим переходы из браузерной строки на конкретные страницы Svelte.

Идея с переходами по url взята отсюда:
github.com/bluwy/svelte-url

Это небольшой файл url.js, который надо положить к себе.

Index.svelte

Входная страница Index.svelte. В ней мы загружаем наше меню. Оно всегда неизменно и не будет перезагружаться при переходе по ссылкам. Затем добавляем на эту же страницу (она же является главной) обработку url запросов. В зависимости от ссылки указывает страницу перехода. Эти же страницы указаны в меню Nav.svelte.

<script>
    import url from './assets/js/url'
    import Nav from "./Nav.svelte";
    import Main from './pages/Main.svelte';
    import Page1 from './pages/Page1.svelte';
    import Page2 from './pages/Page2.svelte';
</script>

<Nav/>

<!-- Переход из URL на страницы -->
{#if $url.hash === '' || $url.hash === '#/'}
    <Main/>
{:else if $url.hash === '#/Page1'}
    <Page1/>
{:else if $url.hash === '#/Page2'}
    <Page2/>
{:else}
    <h1>404</h1>
{/if}

Nav.svelte

Страница с меню и выделения текущей ссылки на Svelte.

Собираем наше меню из нужных нам страниц:

<script>
    import url from './assets/js/url'

    let menu = 0;
    let links = [
        {
            'page': '#/Main',
            'name': 'Главная'
        },
        {
            'page': '#/Page1',
            'name': 'Название ссылки страницы 1'
        },
        {
            'page': 'Page2',
            'name': 'Название ссылки страницы 2'
        },
    ]

    // Selected page
    let current = '';
    let selected;
</script>

Выводим меню на сайте:

<ul class="menu">
    {#each links as link, id}
    <li>
        {#if link.page === 'Main'}
            <a href="/#"
               class:selected="{$url.hash === ''}"
               on:click="{() => current = id}"
               on:click={() => menu = id}
            >
                {link.name}
            </a>
        {:else}
            <a href="#/{link.page}"
               class:selected="{$url.hash === link.page}"
               on:click="{() => current = id}"
               on:click={() => menu = id}
            >
                {link.name}
            </a>
        {/if}
        </li>
    {/each}
</ul>

Добавляем стили scss на Svelte:

<style lang="scss">
    //@import 'assets/scss/app';

    .menu {
        display: flex;
        justify-content: space-evenly;
        flex-wrap: wrap;
        border-bottom: 1px solid #CCCCCC;
        margin: 0;
        padding: 0;

        li {
            list-style: none;
            display: inline;
        }

        a {
            padding: 0.5em 0.75em;
            border-bottom: 2px solid transparent;
            cursor: pointer;
            list-style: none;
            display: inline-block;

            &.selected {
                border-bottom: 2px solid #4F81E5;
                color: #4F81E5;
            }

            &:hover {
                text-decoration: none;
                color: darkred;
            }
        }
    }
</style>

За выделение текущей ссылки (страницы) отвечают эти участки:

// Selected page
let current = '';
let selected;

class:selected="{$url.hash === '#/' + link.page}"
on:click="{() => current = id}"
on:click={() => menu = id}

Nav.svelte с иконками

Немного модифицированный вариант под иконки.

JS:

<script>
    import url from './assets/js/url'

    let menu = 0;
    let links = [
        {
            // 'name': 'Графики',
            'link': '#/Charts',
            'hash': '#/Charts',
            'class': 'icon-chart',
        },
        {
            // 'name': 'Главная',
            'link': '/#',
            'hash': '',
            'class': 'icon-add',
        },
        {
            // 'name': 'Админка',
            'link': '/admin/',
            'class': 'icon-settings'
        }
    ]

    // Selected page
    let current = '';
    let selected;
</script>

Основной код:

<ul class="menu">
    {#each links as item, id}
        <li class="menu-container js-menu-container">
            <a href="{item.link}"
               class:selected="{$url.hash === item.hash}"
               on:click="{() => current = id}"
               on:click={() => menu = id}>
                <div class="icon-menu {item.class}"></div>
            </a>
        </li>
    {/each}
</ul>

Стили:

<style lang="scss">
    //@import 'assets/scss/app';

    .menu {
        display: flex;
        justify-content: space-evenly;
        flex-wrap: wrap;
        position: fixed;
        z-index: 99;
        width: 100%;
        margin: 0;
        left: 0;
        bottom: 0;
        background-color: #cdd5e2;
        align-items: baseline;
        overflow: hidden;
        padding: 0;

        li {
            list-style: none;
            display: inline;
        }

        a {
            border-bottom: 2px solid transparent;
            cursor: pointer;
            list-style: none;
            display: inline-block;
            padding: 0.5em 0.75em;
            color: #000;

            &.selected {
                border-bottom: 2px solid #4F81E5;
                color: #4F81E5;
            }

            &:hover {
                text-decoration: none;
                color: darkred;
            }
        }

        .icon-menu {
            height: 30px;
            width: 30px;
            padding: 5px;
            cursor: pointer;
        }

        .icon-chart {
            background-color: black;
            mask-image: url("");

            &:hover {
                background-color: red;
            }
        }

        .icon-add {
            background-color: black;
            mask-image: url("");
            mask-repeat: no-repeat;
            mask-size: contain;
            mask-position: center;

            &:hover {
                background-color: red;
            }
        }

        .icon-settings {
            background-color: black;
            mask-image: url("");
            mask-repeat: no-repeat;
            mask-size: contain;
            mask-position: center;

            &:hover {
                background-color: red;
            }
        }
    }
</style>

Кстати, на сайте нет рекламы. У сайта нет цели самоокупаться, но если вам пригодилась информация можете задонатить мне на чашечку кофе в макдаке. Лайкнуть страницу или просто поблагодарить. Карма вам зачтется.

Добавить комментарий

Напишите свой комментарий, если вам есть что добавить/поправить/спросить по теме текущей статьи:
"Svelte — меню и меняющиеся url"