diff --git a/src/BootstrapBlazor.Server/Components/Samples/Reconnectors.razor b/src/BootstrapBlazor.Server/Components/Samples/Reconnectors.razor
index e74fbfacfa7..102b9a21cee 100644
--- a/src/BootstrapBlazor.Server/Components/Samples/Reconnectors.razor
+++ b/src/BootstrapBlazor.Server/Components/Samples/Reconnectors.razor
@@ -16,9 +16,11 @@
</div>
// add ReconnectorOutlet component
-<component type="typeof(ReconnectorOutlet)" param-AutoReconnect="true" render-mode="ServerPrerendered" />
+<ReconnectorOutlet AutoReconnect="true" ReconnectInterval="5000" @@rendermode="new InteractiveServerRenderMode(false)" />
-
组件参数 AutoReconnect 用于控制是否开启网络重连,默认 true 已开启,可以通过 param-AutoReconnect="false" 关闭
+AutoReconnect 用于控制是否在连接中断后自动检测服务是否恢复。默认 true;检测到服务恢复时,页面会自动重新加载。设置为 false 可关闭此行为。
+
+ReconnectInterval 用于设置检测间隔,默认 5000 毫秒,最小值为 1000 毫秒。
@((MarkupString)Localizer["Step2"].Value)
@@ -269,3 +271,5 @@
</ReconnectRejectedTemplate>
+
+
diff --git a/src/BootstrapBlazor/Components/Reconnector/ReconnectorContent.razor b/src/BootstrapBlazor/Components/Reconnector/ReconnectorContent.razor
index bbec66f16c0..c8591c0fec7 100644
--- a/src/BootstrapBlazor/Components/Reconnector/ReconnectorContent.razor
+++ b/src/BootstrapBlazor/Components/Reconnector/ReconnectorContent.razor
@@ -1,6 +1,6 @@
@namespace BootstrapBlazor.Components
@inherits BootstrapModuleComponentBase
-@attribute [BootstrapModuleAutoLoader("Reconnector/ReconnectorContent.razor.js", AutoInvokeDispose = false)]
+@attribute [BootstrapModuleAutoLoader("Reconnector/ReconnectorContent.razor.js")]
diff --git a/src/BootstrapBlazor/Components/Reconnector/ReconnectorContent.razor.cs b/src/BootstrapBlazor/Components/Reconnector/ReconnectorContent.razor.cs
index 9b966d50559..7779f1b530e 100644
--- a/src/BootstrapBlazor/Components/Reconnector/ReconnectorContent.razor.cs
+++ b/src/BootstrapBlazor/Components/Reconnector/ReconnectorContent.razor.cs
@@ -67,7 +67,7 @@ protected override async Task InvokeInitAsync()
{
if (AutoReconnect)
{
- await InvokeVoidAsync("reconnect", Math.Max(1000, ReconnectInterval));
+ await InvokeVoidAsync("init", Id, Math.Max(1000, ReconnectInterval));
}
}
diff --git a/src/BootstrapBlazor/Components/Reconnector/ReconnectorContent.razor.js b/src/BootstrapBlazor/Components/Reconnector/ReconnectorContent.razor.js
index 35607e281e6..e4378ff5cd1 100644
--- a/src/BootstrapBlazor/Components/Reconnector/ReconnectorContent.razor.js
+++ b/src/BootstrapBlazor/Components/Reconnector/ReconnectorContent.razor.js
@@ -1,26 +1,93 @@
-export function reconnect(interval) {
- const reconnectHandler = setInterval(async () => {
- const com = document.getElementById('components-reconnect-modal')
- if (com) {
- if (com.classList.length === 0 || com.classList.contains('components-reconnect-hide')) {
- return
- }
- else {
- clearInterval(reconnectHandler)
-
- async function attemptReload() {
- try {
- await fetch('')
- if (reloadHandler) {
- clearInterval(reloadHandler)
- }
- location.reload()
- }
- catch { }
- }
- await attemptReload()
- const reloadHandler = setInterval(attemptReload, interval)
+import EventHandler from "../../modules/event-handler.js"
+import Data from "../../modules/data.js"
+
+export function init(id, interval) {
+ dispose(id);
+
+ const modal = document.getElementById('components-reconnect-modal');
+ if (modal === null) {
+ return;
+ }
+
+ let reloadHandler;
+ let reloadInProgress = false;
+ let disposed = false;
+
+ const stopReloading = () => {
+ if (reloadHandler !== undefined) {
+ clearInterval(reloadHandler);
+ reloadHandler = undefined;
+ }
+ };
+
+ const attemptReload = async () => {
+ if (disposed || reloadInProgress) {
+ return;
+ }
+
+ try {
+ const response = await fetch('', { cache: 'no-store' });
+ if (!disposed && response.ok) {
+ reloadInProgress = true;
+ stopReloading();
+ location.reload();
}
}
- }, interval)
+ catch {
+ }
+ };
+
+ const startReloading = () => {
+ if (reloadHandler !== undefined) {
+ return;
+ }
+
+ reloadHandler = setInterval(attemptReload, interval);
+ void attemptReload();
+ };
+
+ const updateReloading = () => {
+ if (modal.classList.length === 0 || modal.classList.contains('components-reconnect-hide')) {
+ stopReloading();
+ }
+ else {
+ startReloading();
+ }
+ };
+
+ const stateChanged = event => {
+ if (event.detail?.state === 'hide') {
+ stopReloading();
+ }
+ else {
+ startReloading();
+ }
+ };
+
+ const observer = new MutationObserver(updateReloading);
+ observer.observe(modal, { attributes: true, attributeFilter: ['class'] });
+ EventHandler.on(modal, 'components-reconnect-state-changed.bb.reconnector', stateChanged);
+
+ Data.set(id, {
+ modal,
+ observer,
+ stateChanged,
+ dispose: () => {
+ disposed = true;
+ stopReloading();
+ }
+ });
+ updateReloading();
+}
+
+export function dispose(id) {
+ const reconnector = Data.get(id);
+ if (reconnector === null) {
+ return;
+ }
+
+ Data.remove(id);
+ reconnector.observer.disconnect();
+ EventHandler.off(reconnector.modal, 'components-reconnect-state-changed.bb.reconnector', reconnector.stateChanged);
+ reconnector.dispose();
}