【问题标题】:Change active navbar link using JavaScript in ASP.NET Core Razor Pages在 ASP.NET Core Razor 页面中使用 JavaScript 更改活动导航栏链接
【发布时间】: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 或其他方式。

标签: javascript asp.net-core bootstrap-4 razor-pages


【解决方案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 提供的解决方案似乎非常适合这种情况,因为您对每一页使用一个代码。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-09
      • 1970-01-01
      • 1970-01-01
      • 2019-05-06
      • 1970-01-01
      • 1970-01-01
      • 2013-01-12
      相关资源
      最近更新 更多