在 ASP.NET Core Razor 页面中使用 JavaScript 更改活动导航栏链接

Posted

技术标签:

【中文标题】在 ASP.NET Core Razor 页面中使用 JavaScript 更改活动导航栏链接【英文标题】:Change active navbar link using JavaScript in ASP.NET Core Razor Pages 【发布时间】:2021-07-06 08:37:46 【问题描述】:

当我浏览我的Razor-Pages 时,我需要更改导航栏链接颜色。我尝试使用javascript,但似乎每次转到另一个页面时页面都会重新呈现,我无法toggle我的元素。

这是我迄今为止尝试过的:

导航栏链接

<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between ml-5">
                 <ul class="navbar-nav flex-grow-1">
                    <li class="nav-item">
                        <a class="nav-link active-link" asp-area="" asp-page="/Index">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" asp-area="" asp-page="/Privacy">Privacy</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" asp-page="/Movies/Index">Movies</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" asp-page="/Genres/Index">Genres</a>
                    </li>
                </ul>
</div>

site.js

const links = document.querySelectorAll('.nav-link');
let currentActive = document.querySelector('.active-link');

const changeClass = (e) => 
    //e.preventDefault();
    currentActive.classList.remove('active-link');
    e.target.classList.add('active-link');
;

links.forEach((el) => el.addEventListener('click', changeClass));

在这里,我将当前的active link 保存在我的js 中,当我导航到另一个页面时,该页面会重新呈现,并且我的js 文件会再次重新加载,以便我之前的值设置回默认active link

我有什么:

我想要的:

我找到了一个possible solution,但它似乎有点硬编码和工作,我相信应该有更好的方法。

附:理想情况下,使用JavaScript 的解决方案是最好的,但是,我不会在这里坚持任何事情。

【问题讨论】:

你在使用一些前端框架吗?还是纯 html 和 JS,每个实现的 html 页面中的 header 都在哪里? 好吧,我使用默认的 UI 设置 bootstrap,还有 jquery,但是对于这个问题,我使用普通的 js,因为我只是玩玩,想看看它对我即将到来的项目有何影响,以便我决定是否继续使用pure js 或其他方式。 【参考方案1】:

使用DOMContentLoaded 事件而不是点击事件。这样,更改将在呈现后应用于实际页面。目前,您正在将更改应用到您正在导航的页面上的链接:

document.addEventListener('DOMContentLoaded', () => 
    document.querySelectorAll('.nav-link').forEach(link => 
        if (link.getAttribute('href').toLowerCase() === location.pathname.toLowerCase()) 
            link.classList.add('active-link');
         else 
            link.classList.remove('active-link');
        
    );
)

【讨论】:

【参考方案2】:

不一定需要javascript。 TagHelpers 可用于服务器端解决方案,请参阅我对类似问题的回答 here。

例如,标签助手使用导航栏元素上的自定义属性来描述每个链接对应的页面。然后标签助手处理属性时,将值与当前地址进行比较,如果匹配,则添加active类。

它还删除了该属性,以便用户无法在响应 HTML 中使用它。在服务器端执行此操作还可以确保禁用 javascript 的用户可以使用高亮显示。

【讨论】:

【参考方案3】:

我遇到了同样的问题并开始使用这种方法:为每个页面创建不同的布局。每个布局都突出显示了感兴趣的链接。问题是您有许多布局,只是在导航栏链接中进行了微小的更改。

所以,我决定改进解决方案,我终于比预期的要简单得多:

这里是第二种方法的sn-p:

// _Layout.cshtml

<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">VS22Netcore01</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul id="mainMenu" class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            **<a id="linkHome"** class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            **<a id="linkPrivacy"** class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                        <li class="nav-item">
                            **<a id="linkAbout"** class="nav-link text-dark" asp-area="" asp-page="/About">Acerca de</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()  <!-- inserta la pagina en el container -->
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2021 - VS22Netcore01 - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    **@await RenderSectionAsync("Scripts", required: true)**
</body>

请注意双星号之间的代码。

然后,在每个内容页面中,我添加了如下内容:

//Privacy.cshtml, a sample page
@page
@model PrivacyModel
@
    ViewData["Title"] = "Privacy Policy";

<h1>@ViewData["Title"]</h1>

<p>Use this page to detail your site's privacy policy.</p>



@section Scripts 

<script>        
    **$('#linkPrivacy').removeClass('text-dark');
    $('#linkPrivacy').addClass('text-info');**
</script>

如您所见,每个内容页面中的脚本都会更改链接的样式。 这样你就有了不同的“稍微”页面。

问候

【讨论】:

这个解决方案似乎有效。但是,如果问题会包括所有页面,那么您可能需要使用另一种方法,因为它不利于 DRY,而且通常很容易被遗忘。假设您有 20-25 页,这会增加代码量并降低可读性。对我来说,@Mike Brind 提供的解决方案似乎非常适合这种情况,因为您对每一页使用一个代码。

以上是关于在 ASP.NET Core Razor 页面中使用 JavaScript 更改活动导航栏链接的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ASP.Net Core Razor 页面上重定向

ASP .NET Core Razor 页面中的授权

Asp.net core razor pages 加载部分页面

Asp.Net Core Razor 页面中的远程验证

ASP.NET Core Razor 页面与完整 MVC Core [关闭]

Asp .NET Core 2.2 Razor 页面布局和局部