Как динамически изменять один и тот же макет в Blazor Webassembly с помощью входного параметра

#blazor #blazor-server-side #blazor-client-side #blazor-webassembly

#blazor #blazor-на стороне сервера #blazor-на стороне клиента #blazor-webassembly

Вопрос:

У меня есть этот вариант использования для изменения пункта меню родительского макета на основе выбранной страницы razor. Для простоты в приведенном ниже примере кода макета я пытаюсь увидеть, какая дочерняя страница Razor пытается загрузить пункт меню, и изменить пункт меню на основе этого.
Я пытаюсь избежать создания нескольких файлов макета. Если я правильно понимаю, макеты загружаются только один раз в жизненном цикле, если вы не обновите браузер, пожалуйста, дайте мне знать, возможно ли это вообще.

 @inherits LayoutComponentBase
    <ul id="zMenu">
    @if (RouteName.Contains("/packing_sky/"))
    {
    <li class='title'>Sky Packing</li>
    <li><a href='/Packing_sky'>Pack</a></li>
    }
    else if (RouteName.Contains("/cartpick/")) {
    <li class='title'>Sky Packing</li>
    <li><a href='/CartPick'>Pack</a></li>
    }
    </div>
@code{
    public String RouteName= "";
    protected override void OnInitialized()
    {
        RouteName= "<from_razor_page>";
    }
}
 

Заранее спасибо.

Ответ №1:

Я думаю, что есть два способа добиться такого поведения.

Я вызову компонент компоновки MainLayout .

В первом подходе MainLayout он отвечает за «знание» того, какая ссылка должна быть отображена. По сути, это то, что вы уже сделали. NavigationManager Имеет необходимые свойства для текущего URL. Итак, вам нужно его внедрить.

 @inject NavigationManager navManager
 

Вы также правы в том, что OnInitialized метод of MainLayout будет вызван только один раз. (Чтобы быть более ценным, он не будет вызван снова, если страница использует тот же макет). Однако у NavigationManager него есть событие, на которое вы можете подписаться.

 @code{
    public String RouteName = "";

    private void HandleLocactionChanged(Object sender,LocationChangedEventArgs args)
    {
        RouteName = args.Location;
        //force an update of the UI, it might be necessary in some layouts and circumstances
        StateHasChanged();
    }

    protected override void OnInitialized()
    {
        RouteName = navManager.Uri;
        navManager.LocationChanged  = HandleLocactionChanged;
    }

    public void Dispose()
    {
        navManager.LocationChanged -= HandleLocactionChanged;
    }
}
 

Вызов StateHasChanged() в HandleLocactionChanged методе гарантирует, что макет обновляется с новым значением. Это может быть необязательно для каждого макета и при любых обстоятельствах. Я бы рекомендовал протестировать его без него, и если это не сработает, попробуйте с StateHasChanged() ним .

Я реализовал IDisposable интерфейс для отказа от подписки на событие. Это полезно только в том случае, если ваше приложение имеет несколько макетов.

Второй подход заключается в использовании сервиса для связи между компонентом MainLayout и вашей страницей. Это похоже на то, что страница «запрашивает» отображение ссылки.

Если вас заинтересовало это решение, дайте мне знать, и я опубликую его.

Ответ №2:

Спасибо, подход № 1 избавил меня от большого дублирования кода. Мне пришлось внести одно незначительное изменение в метод HandleLocactionChanged. Поэтому мне пришлось снова перестроить HTML-содержимое и установить его с помощью javascript, поскольку страница уже загружена.

 private void HandleLocationChanged(Object sender, LocationChangedEventArgs args)
{
    RouteName = args.Location;
    JSRuntime.InvokeVoidAsync(
                    "setHTML", new String[]{"zMenu", fetchMenuContent(RouteName)});
}
 

Комментарии:

1. Не могли бы вы попробовать вызвать StateHasChanged() вместо вызова функции javascript? Он должен работать без дополнительного javascript.

2. Это потрясающе!! Просто попробовал, и все сработало, как ожидалось. Теперь мне не нужен какой-либо исправленный JS-код. Еще раз спасибо!

3. Это здорово. Я обновил свой первоначальный ответ. Было бы неплохо, если бы вы могли принять ответ, чтобы другим было легче найти решение.