Прокрутите до указанной части страницы при нажатии верхней навигационной ссылки в Blazor

Как я могу сделать простой переход к части уже загруженной страницы в Blazor? Вот так в HTML:

<a href = "#contact">Contact us</a>
...
<section id = "contact">

В идеале я также хочу, чтобы он плавно прокручивался до этого раздела. Думал, что попытаюсь решить это с помощью CSS, но, может быть, это невозможно?

Возможный дубликат Автофокус на элементе <a> без JavaScript

Babak Naffas 15.03.2019 17:28

@BabakNaffas, этот метод обычно не работает с приложениями SPA, такими как Blazor.

Kirk Woll 15.03.2019 17:43

Спасибо @KirkWoll. Хорошо знать.

Babak Naffas 15.03.2019 19:26
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
18
3
12 518
5

Ответы 5

Что вам нужно, так это функции хэшированных маршрутов Blazor. Но, увы, таких функций пока нет. Я предлагаю вам использовать JSIterop для выполнения этой задачи: создайте JavaScript, который выполняет навигацию, и передайте ему объект ElementRef.

Надеюсь это поможет...

Редактировать: Ниже приведена адаптация лучшего обходного решения, которое я нашел в Github...

Обычно, когда вы нажимаете ссылку на контакт, вы перенаправляетесь на маршрут http://локальный: 5000/моя страница#контакт, но окажетесь в верхней части страницы. Фрагмент маршрута не используется для выбора конкретного HTML-элемента.

Текущий обходной путь — написать явный код, который интерпретирует URL-адрес. В приведенном выше примере мы могли бы использовать немного JavaScript, а затем вызвать его из нашего кода Blazor:

моя страница.cshtml:

         @page "/mypage"
    @inject Microsoft.AspNetCore.Components.Services.IUriHelper UriHelper

    <nav>

        <a href = "#contact">contact</a>


    </nav>


    <section>
        <h2 id = "contact">contact</h2>

    </section>


@functions {
    protected override void OnInit()
    {
        NavigateToElement();
        UriHelper.OnLocationChanged += OnLocationChanges;
    }

    private void OnLocationChanges(object sender, string location) => NavigateToElement();

    private void NavigateToElement()
    {
        var url = UriHelper.GetAbsoluteUri();
        var fragment = new Uri(url).Fragment;

        if (string.IsNullOrEmpty(fragment))
        {
            return;
        }

        var elementId = fragment.StartsWith("#") ? fragment.Substring(1) : fragment;

        if (string.IsNullOrEmpty(elementId))
        {
            return;
        }

        ScrollToElementId(elementId);
    }

    private static bool ScrollToElementId(string elementId)
    {
        return JSRuntime.Current.InvokeAsync<bool>("scrollToElementId", elementId).GetAwaiter().GetResult();
    }
}

индекс.html:

<script>
        window.scrollToElementId = (elementId) => {
            console.info('scrolling to element', elementId);
            var element = document.getElementById(elementId);
            if (!element)
            {
                console.warn('element was not found', elementId);
                return false;
            }
            element.scrollIntoView();
            return true;
        }
</script>

Примечание. Если вы используете Blazor версии .9.0, вам следует внедрить IJSRuntime Пожалуйста, дайте мне знать, если это решение работает для вас...

Хороший Исаак, помните, что JSRuntime.Current больше не поддерживается. Теперь ( >= 0.9.0 ) вы должны создать экземпляр JSRuntime через DI. :)

dani herrera 16.03.2019 14:26

Пробовал. Microsoft Edge прокручивается до нужной области, затем не реагирует, когда я нажимаю другие ссылки в навигации. Chrome и Firefox вообще не прокручиваются, и при переходе по другим ссылкам в навигации ничего не происходит. Тем не менее, действительно цените усилия! Было бы неплохо, если бы кто-то еще попробовал это, чтобы я знал, есть ли что-то еще на моем сайте, что вызывает проблемы. Обратите внимание, я использую Blazor 0.7.0.

johajan 19.03.2019 23:53

Я попробовал это сейчас в Blazor 0.9.0. С проектом по умолчанию, который создается при создании нового проекта Blazor. Просто чтобы посмотреть, не было ли на моем сайте чего-то странного, что мешало ему работать. Там тоже не работал. На странице github, где вы ее нашли, я вижу, что он прокомментировал: «Предлагаемый обходной путь не работает, так как браузер дает сбой и предназначен только для иллюстрации». Так что нам просто придется подождать, я думаю.

johajan 29.03.2019 02:29

Тот же ответ, что и ответ Исаака, но нужно изменить код.

Я обнаружил, что основная проблема заключается в том, что вам нужно, чтобы он был асинхронным. @johajan

@inject IJSRuntime JSRuntime

...

@functions {
protected override async Task OnInitAsync()
{
    await base.OnInitAsync();
    //NavigateToElement();
    UriHelper.OnLocationChanged += OnLocationChanges;
}

private async Task OnLocationChanges(object sender, string location) => await NavigateToElement();

private async Task NavigateToElement()
{
    var url = UriHelper.GetAbsoluteUri();
    var fragment = new Uri(url).Fragment;

    if (string.IsNullOrEmpty(fragment))
    {
        return;
    }

    var elementId = fragment.StartsWith("#") ? fragment.Substring(1) : fragment;

    if (string.IsNullOrEmpty(elementId))
    {
        return;
    }

    await ScrollToElementId(elementId);
}

private Task<bool> ScrollToElementId(string elementId)
{
    return JSRuntime.InvokeAsync<bool>("scrollToElementId", elementId);
}

}

Я решил эту проблему, используя button, а затем написав в разметке некоторый встроенный Javascript. Вы можете обобщить это на компонент Blazor для получения бонусных баллов!

<button type = "button" onclick = "document.getElementById('contact').scrollIntoView({behavior:'smooth'})">Contact us</button>
...
<section id = "contact">

Спасибо, это почти решило это для меня! Смотрите мое решение, чтобы добавить к этому.

goku_da_master 03.02.2020 07:35

Я не вижу, что отличается от вашего ответа, но рад, что вы на правильном пути

Aaron Hudon 03.02.2020 19:14

Я использовал ответ Аррона Хадона, и он все еще не работал. Однако, поиграв, я понял, что это не сработает с якорным элементом: <a id='star_wars'>Place to jump to</a>. Очевидно, у Blazor и других спа-фреймворков есть проблемы с переходом на якоря на той же странице. Чтобы обойти это, мне пришлось использовать вместо этого элемент абзаца (раздел тоже сработает): <p id='star_wars'>Some paragraph<p>.

Пример использования бутстрапа:

<button class = "btn btn-link" onclick = "document.getElementById('star_wars').scrollIntoView({behavior:'smooth'})">Star Wars</button>

... lots of other text

<p id = "star_wars">Star Wars is an American epic...</p>

Обратите внимание, что я использовал класс начальной загрузки btn-link, чтобы кнопка выглядела как гиперссылка.

Вы можете использовать 2 пакета Nuget, чтобы решить эту проблему:

  1. Прокрутите JS, который является частью JsInterop Nuget. У этого есть много функций, см. документы, но основная часть — это IScrollHandler, который представляет собой инъекционный сервис. Вы можете попробовать это с демо-приложение. Вы можете видеть, что scrollIntoView() и другие функции JS обернуты, доступна плавная прокрутка. Намного проще использовать поддержку прокрутки JS...
  2. Второй вариант — использовать «Пармалинки» в URL-адресе, который у вас есть «#». Нагет доступен здесь. Это то, что вы просили. По сути, он использует теги <a>, но вам не нужно беспокоиться об этом (обратите внимание, что даже демо-приложение имеет # URL-адреса). Также отображает компонент «ссылка» с интерактивным значком и действиями навигации/копирования. В настоящее время плавная прокрутка недоступна, но ее можно запросить. Вы можете попробовать это с демо-приложение. Modal demo

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