原文鏈接:https://blazor-university.com/javascript-interop/calling-javascript-from-dotnet/updating-the-document-title/
更新 document title
源代碼[1]
在創建 Blazor 布局[2]部分中,我們看到了 Blazor 應用程序如何存在于 HTML(或 cshtml)文檔中,并且只能控制主應用程序元素中的內容。
不是單頁應用程序的網站可以通過在 <head>
部分中添加 <title>
元素來指定要在瀏覽器選項卡中顯示的文本,但我們的 Blazor 應用程序實際上并不導航到不同的服務器頁面,因此它們都有與我們的應用程序啟動時加載的文檔標題相同。
我們現在將使用一個新的 <Document>
組件來解決這個問題,該組件將使用 JavaScript 互操作來設置 document.title
,這將反映在瀏覽器的選項卡中。我們將其創建為 Blazor 服務器應用程序;它可以很容易地在可重用的組件庫中創建,但我將把它作為練習留給你。
創建一個新的 Blazor 服務器應用程序,然后在 wwwroot
文件夾中創建一個 scripts
文件夾,并在其中使用以下腳本創建一個名為 DocumentInterop.js
的腳本。
var?BlazorUniversity?=?BlazorUniversity?||?{};
BlazorUniversity.setDocumentTitle?=?function?(title)?{document.title?=?title;
};
這將創建一個名為 BlazorUniversity
的對象,該對象具有一個名為 setDocumentTitle
的函數,該函數接受一個新標題并將其分配給 document.title
。
接下來,編輯 /Pages/_Host.cshtml 文件并添加對我們新腳本的引用。
<script?src="_framework/blazor.server.js"></script>
<script?src="~/scripts/DocumentInterop.js"></script>
最后,我們需要 Document
組件本身。在 /Shared 文件夾中創建一個名為 Document.razor 的新組件并輸入以下標記。
@inject?IJSRuntime?JSRuntime
@code?{[Parameter]public?string?Title?{?get;?set;?}protected?override?async?Task?OnParametersSetAsync(){await?JSRuntime.InvokeVoidAsync("BlazorUniversity.setDocumentTitle",?Title);}
}
這段代碼有一個故意的錯誤。運行應用程序,您將在調用 JSRuntime.InvokeVoidAsync
的行上看到 NullReferenceException
。
原因是 Blazor 在將控制權交給客戶端之前在服務器上運行預渲染階段。此預渲染的目的是從服務器返回有效的渲染 HTML,以便
網絡爬蟲,例如谷歌,可以索引我們的網站。
用戶立即看到結果。
這里的問題是,當預渲染階段運行時,沒有瀏覽器可供 JSRuntime
進行互操作。可能的解決方案是
編輯 /Pages/_Host.cshtml 并將
<component type="typeof(App)" render-mode="ServerPrerendered" />
更改為<component type="typeof(App)" render-mode="Server"/>
優點: 一個簡單的修復。
缺點: 谷歌等在訪問我們網站的頁面時不會看到任何內容。
重寫
OnAfterRenderAsync
而不是OnParametersSetAsync
。
#2是解決問題的正確方法。
@inject?IJSRuntime?JSRuntime
@code?{[Parameter]public?string?Title?{?get;?set;?}protected?override?async?Task?OnAfterRenderAsync(bool?firstRender){if?(firstRender)await?JSRuntime.InvokeVoidAsync("BlazorUniversity.setDocumentTitle",?Title);}
}
正如在 JavaScript 啟動過程一節中所解釋的,當服務器在發送網站之前預渲染網站時,客戶端瀏覽器將在沒有任何 JavaScript 的情況下渲染 App 組件。只有在瀏覽器中呈現 HTML 后,才會調用 OnAfterRender*
方法并將 firstRender
設置為 true
。
使用新的 Document 組件
編輯 /Pages 文件夾中的每個頁面,并添加我們的新元素 <Document Title="Index"/>
- 但顯然您希望在瀏覽器的選項卡中顯示正確的文本。
參考資料
[1]
源代碼: https://github.com/mrpmorris/blazor-university/tree/master/src/JavaScriptInterop/UpdatingDocumentTitle