在Blazor中,如何簡單地“跳轉”到已經加載的頁面?在HTML中是這樣的:
<a href="#contact">Contact us</a>
...
<section id="contact">
理想情況下,我也想讓它順利滾動到這一節。我想我會嘗試用CSS來解決這個問題,但也許不可能?
我通過使用一個按鈕,然后在標記中編寫一些內聯Javascript來解決這個問題。您可以將其推廣到Blazor組件,以獲得加分!
<button type="button" onclick="document.getElementById('contact').scrollIntoView({behavior:'smooth'})">Contact us</button>
...
<section id="contact">
你需要的是Blazor的散列路由特性。但是,唉,這樣的特征還不存在。我建議您使用JSIterop來執行這項任務:創建一個執行導航的JavaScript,并向它傳遞一個ElementRef對象。
希望這有所幫助...
編輯:以下是我在Github中找到的最佳變通解決方案的改編版...
通常,當您單擊contact的鏈接時,您會被重定向到路由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版,您應該注入IJSRuntime 請讓我知道這個解決方案是否適合你...
您可以使用2個Nuget包來解決這個問題:
滾動JS,它是JsInterop Nuget的一部分。這有許多功能,見文檔,但主要部分是IScrollHandler,這是一個可注入的服務。可以用演示app試試。可以看到scrollIntoView()和其他JS函數被包裝,平滑滾動可用。使用JS滾動支持簡單多了... 第二種選擇是使用& quot帕馬林克斯& quot在您的URL中有& quot# & quot。此處不可用。這是你要求的?;旧鲜怯? lta & gt標簽,但你不必為此煩惱(注意,即使是演示應用程序也有# URLs)。還呈現& quot鏈接& quot具有可點擊圖標和導航/復制動作的組件。當前平滑滾動不可用,但可以請求??梢杂醚菔綼pp試試。我用了炎亞綸·胡登的答案,但還是沒用。然而,在玩了一圈之后,我意識到它對錨元素不起作用:& lta id = ' star _ wars ' & gt要跳轉到的位置& lt/a & gt;。顯然,Blazor和其他spa框架在跳轉到同一頁面的錨點時存在問題。為了避免這個問題,我不得不使用段落元素來代替(section也可以):& ltp id = ' star _ wars ' & gt某段& ltp & gt。
使用引導程序的示例:
<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類來使按鈕看起來像一個超鏈接。
與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);
}
}
最簡單的方法如下:
將javascript文件添加到項目中。
在它的內部,添加這個函數:
function ScrollTo(elementId) {
var element = document.getElementById(elementId);
element.scrollIntoView({
behavior: 'smooth'
});}
將腳本引用添加到您的index.html中:
<script src="JavaScript.js"></script>
回到你的頁面,在你的鏈接上添加一個onclick事件:
<a @onclick="(async() => await ScrolltoContact())">Contact</a>
注入IJSRuntime:
@inject IJSRuntime javaScript;
創建調用javascript函數的方法:
async Task ScrolltoContact()
{
await javaScript.InvokeVoidAsync("ScrollTo", "Contact");
}
為了讓@Aaron Hudon的回答更完美一點,我做了如下描述:
<a href="javascript:void(0)" onclick="document.getElementById('contact').scrollIntoView({behavior:'smooth'})">Contact us</a>