单击 Blazor 中的顶部导航链接时滚动到页面的指定部分
Posted
技术标签:
【中文标题】单击 Blazor 中的顶部导航链接时滚动到页面的指定部分【英文标题】:Scroll to specified part of page when clicking top navigation link in Blazor 【发布时间】:2019-08-06 18:43:26 【问题描述】:如何在 Blazor 中对已加载页面进行简单的“跳转”部分?像这样在 html 中:
<a href="#contact">Contact us</a>
...
<section id="contact">
理想情况下,我还希望它平滑地向下滚动到此部分。以为我会尝试用 CSS 解决这个问题,但也许不可能?
【问题讨论】:
Autofocus on <a> element without javascript的可能重复 @BabakNaffas 该技术通常不适用于 Blazor 等 SPA 应用程序。 谢谢@KirkWoll。很高兴知道。 【参考方案1】:您需要的是 Blazor 的散列路由功能。但是,唉,这样的功能还不存在。我建议您使用 JSIterop 来执行此任务:创建一个执行导航的 JavaScript,并将其传递给 ElementRef 对象。
希望对你有帮助……
编辑:以下是我在 Github 中找到的最佳解决方案的改编...
通常,当您单击联系链接时,您会被重定向到路由http://localhost:5000/mypage#contact,但会位于页面顶部。路由的片段不用于选择特定的 HTML 元素。
当前的解决方法是编写解释 URL 的显式代码。在上面的示例中,我们可以使用一点 JavaScript,然后从我们的 Blazor 代码中调用它:
mypage.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();
index.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 请让我知道此解决方案是否适合您...
【讨论】:
不错的 Issac,记住JSRuntime.Current
不再受支持。现在 ( >= 0.9.0 ) 你必须通过 DI 实例化 JSRuntime
。 :)
试过了。 Microsoft Edge 滚动到正确的区域,然后当我单击导航中的其他链接时没有反应。 Chrome 和 Firefox 根本不滚动,点击导航中的其他链接时也没有任何反应。真的很感谢你的努力!如果其他人尝试过会很好,所以我知道我的网站中是否有其他东西导致问题。请注意,我正在运行 Blazor 0.7.0
我现在已经在 Blazor 0.9.0 中尝试过了。使用创建新 Blazor 项目时创建的默认项目。只是想看看我的网站中是否有什么奇怪的东西阻止了它的工作。也没有在那里工作。在您找到它的 github 页面中,我看到他评论了“建议的解决方法不起作用,因为浏览器崩溃并且仅用于说明。”所以我猜我们只需要等待。【参考方案2】:
和Issac的回答一样,但是需要改一些代码。
我发现主要问题是您需要它是异步的。 @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);
【讨论】:
【参考方案3】:我通过使用button
然后在标记中编写一些内联Javascript 解决了这个问题。您可以将此推广到 Blazor 组件以获得奖励积分!
<button type="button" onclick="document.getElementById('contact').scrollIntoView(behavior:'smooth')">Contact us</button>
...
<section id="contact">
【讨论】:
谢谢,这几乎为我解决了!请参阅我的解决方案以添加到此解决方案。 我看不出与您的回答有何不同,但很高兴它让您走上了正轨【参考方案4】:我使用了 Arron Hudon 的答案,但仍然没有用。然而,在玩了之后,我意识到它不适用于锚元素:<a id='star_wars'>Place to jump to</a>
。显然 Blazor 和其他 spa 框架在跳转到同一页面上的锚时存在问题。为了解决这个问题,我不得不改用段落元素(部分也可以):<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>
请注意,我使用 bootstrap 的 btn-link
类使按钮看起来像一个超链接。
【讨论】:
【参考方案5】:你可以使用 2 个 Nuget 包来解决这个问题:
-
Scroll JS 是 JsInterop Nuget 的一部分。这有很多功能,请参阅文档,但主要部分是
IScrollHandler
,这是一个可注入服务。您可以使用demo app 进行尝试。可以看到scrollIntoView()
等JS函数包裹,平滑滚动可用。使用 JS 滚动支持要简单得多...
第二个选项是在您拥有“#”的 URL 中使用“Parmalinks”。 Nuget 在这里可用。这是你要求的。基本上它使用<a>
标签,但您不必费心(注意即使是演示应用程序也有# URL)。还呈现带有可点击图标和导航/复制操作的“链接”组件。当前平滑滚动不可用,但可以请求。您可以通过demo app 试用。
【讨论】:
以上是关于单击 Blazor 中的顶部导航链接时滚动到页面的指定部分的主要内容,如果未能解决你的问题,请参考以下文章