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"