fix(module: modal): repeated cleaning dom (#3665) (#3673)

* fix: repeated cleaning dom

* fix: OOM

* fix build

* fix lint

* remove the event handler

* remove handler after element was deleted

---------

Co-authored-by: James Yeung <shunjiey@hotmail.com>
This commit is contained in:
zxyao 2024-02-28 23:29:48 +08:00 committed by GitHub
parent 28e195806d
commit bfb9e3a56f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 227 additions and 148 deletions

View File

@ -14,7 +14,12 @@
"indent": [ "indent": [
"error", "error",
2, 2,
{ "ignoreComments": true } {
"ignoreComments": true,
"SwitchCase": 1,
"flatTernaryExpressions": false,
"offsetTernaryExpressions": false
}
] ]
} }
} }

View File

@ -1,8 +1,7 @@
import { domInfoHelper } from './exports' import { domInfoHelper } from "./exports";
import { styleHelper } from '../styleHelper' import { styleHelper } from "../styleHelper";
import { state } from '../stateProvider' import { state } from "../stateProvider";
import * as enums from '../enums'; import * as enums from "../enums";
let cachedScrollBarSize: number | undefined = undefined; let cachedScrollBarSize: number | undefined = undefined;
const scrollIds = new Map<HTMLElement, number>(); const scrollIds = new Map<HTMLElement, number>();
@ -75,11 +74,14 @@ export class manipulationHelper {
this.fallbackCopyTextToClipboard(text); this.fallbackCopyTextToClipboard(text);
return; return;
} }
navigator.clipboard.writeText(text).then(function () { navigator.clipboard.writeText(text).then(
console.log('Async: Copying to clipboard was successful!'); function () {
}, function (err) { console.log("Async: Copying to clipboard was successful!");
console.error('Async: Could not copy text: ', err); },
}); function (err) {
console.error("Async: Could not copy text: ", err);
}
);
} }
private static fallbackCopyTextToClipboard(text) { private static fallbackCopyTextToClipboard(text) {
@ -100,7 +102,7 @@ export class manipulationHelper {
const msg = successful ? 'successful' : 'unsuccessful'; const msg = successful ? 'successful' : 'unsuccessful';
console.log('Fallback: Copying text command was ' + msg); console.log('Fallback: Copying text command was ' + msg);
} catch (err) { } catch (err) {
console.error('Fallback: Oops, unable to copy', err); console.error("Fallback: Oops, unable to copy", err);
} }
document.body.removeChild(textArea); document.body.removeChild(textArea);
@ -108,11 +110,12 @@ export class manipulationHelper {
static focus(selector, noScroll: boolean = false, option: enums.FocusBehavior = enums.FocusBehavior.FocusAtLast) { static focus(selector, noScroll: boolean = false, option: enums.FocusBehavior = enums.FocusBehavior.FocusAtLast) {
const dom = domInfoHelper.get(selector); const dom = domInfoHelper.get(selector);
if (!(dom instanceof HTMLElement)) if (!(dom instanceof HTMLElement))
throw new Error("Unable to focus on invalid element."); throw new Error("Unable to focus on invalid element.");
dom.focus({ dom.focus({
preventScroll: noScroll preventScroll: noScroll,
}); });
if (dom instanceof HTMLInputElement || dom instanceof HTMLTextAreaElement) { if (dom instanceof HTMLInputElement || dom instanceof HTMLTextAreaElement) {
@ -130,7 +133,6 @@ export class manipulationHelper {
} }
} }
static blur(selector) { static blur(selector) {
const dom = domInfoHelper.get(selector); const dom = domInfoHelper.get(selector);
if (dom) { if (dom) {
@ -147,7 +149,11 @@ export class manipulationHelper {
} }
} }
static smoothScrollTo(selector: Element | string, parentElement: HTMLElement, duration: number) { static smoothScrollTo(
selector: Element | string,
parentElement: HTMLElement,
duration: number
) {
const element = domInfoHelper.get(selector); const element = domInfoHelper.get(selector);
const to = element.offsetTop; const to = element.offsetTop;
if (scrollIds.get(parentElement)) { if (scrollIds.get(parentElement)) {
@ -180,13 +186,20 @@ export class manipulationHelper {
static slideTo(targetPageY) { static slideTo(targetPageY) {
const timer = setInterval(function () { const timer = setInterval(function () {
const currentY = document.documentElement.scrollTop || document.body.scrollTop; const currentY =
const distance = targetPageY > currentY ? targetPageY - currentY : currentY - targetPageY; document.documentElement.scrollTop || document.body.scrollTop;
const distance =
targetPageY > currentY
? targetPageY - currentY
: currentY - targetPageY;
const speed = Math.ceil(distance / 10); const speed = Math.ceil(distance / 10);
if (currentY === targetPageY) { if (currentY === targetPageY) {
clearInterval(timer); clearInterval(timer);
} else { } else {
window.scrollTo(0, targetPageY > currentY ? currentY + speed : currentY - speed); window.scrollTo(
0,
targetPageY > currentY ? currentY + speed : currentY - speed
);
} }
}, 10); }, 10);
} }
@ -216,11 +229,13 @@ export class manipulationHelper {
}); });
state.oldBodyCacheStack.push(oldBodyCache); state.oldBodyCacheStack.push(oldBodyCache);
const scrollBarSize = this.getScrollBarSize(); const scrollBarSize = this.getScrollBarSize();
styleHelper.css(body, styleHelper.css(body, {
{ position: "relative",
"position": "relative", width:
"width": this.hasScrollbar() && scrollBarSize > 0 ? `calc(100% - ${scrollBarSize}px)` : null, this.hasScrollbar() && scrollBarSize > 0
"overflow": "hidden" ? `calc(100% - ${scrollBarSize}px)`
: null,
overflow: "hidden",
}); });
styleHelper.addCls(document.body, "ant-scrolling-effect"); styleHelper.addCls(document.body, "ant-scrolling-effect");
} }
@ -229,9 +244,8 @@ export class manipulationHelper {
if (force) { if (force) {
state.oldBodyCacheStack = []; state.oldBodyCacheStack = [];
} }
const oldBodyCache = state.oldBodyCacheStack.length > 0 ? state.oldBodyCacheStack.pop() : {}; const oldBodyCache = state.oldBodyCacheStack.length > 0 ? state.oldBodyCacheStack.pop() : {};
styleHelper.css(document.body, styleHelper.css(document.body,
{ {
"position": oldBodyCache["position"] ?? null, "position": oldBodyCache["position"] ?? null,
@ -244,9 +258,11 @@ export class manipulationHelper {
static hasScrollbar = () => { static hasScrollbar = () => {
const overflow = document.body.style.overflow; const overflow = document.body.style.overflow;
if (overflow && overflow === "hidden") return false; if (overflow && overflow === "hidden") return false;
return document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight); return (
} document.body.scrollHeight >
(window.innerHeight || document.documentElement.clientHeight)
);
};
/** /**
* getScrollBarSize * getScrollBarSize

View File

@ -11,11 +11,22 @@ namespace AntDesign
[Inject] [Inject]
private DrawerService DrawerService { get; set; } private DrawerService DrawerService { get; set; }
[Inject]
private NavigationManager NavigationManager { get; set; }
protected override void OnInitialized() protected override void OnInitialized()
{ {
DrawerService.OnCloseEvent += DrawerService_OnClose; DrawerService.OnCloseEvent += DrawerService_OnClose;
DrawerService.OnOpenEvent += DrawerService_OnCreate; DrawerService.OnOpenEvent += DrawerService_OnCreate;
DrawerService.OnUpdateEvent += DrawerService_OnUpdateEvent; DrawerService.OnUpdateEvent += DrawerService_OnUpdateEvent;
NavigationManager.LocationChanged += OnLocationChanged;
}
private void OnLocationChanged(object sender, EventArgs e)
{
_drawerRefs.Clear();
InvokeStateHasChanged();
} }
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
@ -23,6 +34,7 @@ namespace AntDesign
DrawerService.OnCloseEvent -= DrawerService_OnClose; DrawerService.OnCloseEvent -= DrawerService_OnClose;
DrawerService.OnOpenEvent -= DrawerService_OnCreate; DrawerService.OnOpenEvent -= DrawerService_OnCreate;
DrawerService.OnUpdateEvent -= DrawerService_OnUpdateEvent; DrawerService.OnUpdateEvent -= DrawerService_OnUpdateEvent;
NavigationManager.LocationChanged -= OnLocationChanged;
base.Dispose(disposing); base.Dispose(disposing);
} }

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
@ -12,6 +13,9 @@ namespace AntDesign
[Inject] [Inject]
private ConfirmService ConfirmService { get; set; } private ConfirmService ConfirmService { get; set; }
[Inject]
private NavigationManager NavigationManager { get; set; }
private readonly List<ConfirmRef> _confirmRefs = new List<ConfirmRef>(); private readonly List<ConfirmRef> _confirmRefs = new List<ConfirmRef>();
#region override #region override
@ -27,10 +31,18 @@ namespace AntDesign
ModalService.OnConfirmUpdateEvent += OnConfirmUpdate; ModalService.OnConfirmUpdateEvent += OnConfirmUpdate;
ConfirmService.OnOpenEvent += OnConfirmOpen; ConfirmService.OnOpenEvent += OnConfirmOpen;
NavigationManager.LocationChanged += OnLocationChanged;
} }
#endregion #endregion
private void OnLocationChanged(object sender, EventArgs e)
{
_confirmRefs.Clear();
InvokeStateHasChanged();
}
/// <summary> /// <summary>
/// create and open a Confirm dialog /// create and open a Confirm dialog
/// </summary> /// </summary>
@ -116,6 +128,7 @@ namespace AntDesign
ModalService.OnConfirmUpdateEvent -= OnConfirmUpdate; ModalService.OnConfirmUpdateEvent -= OnConfirmUpdate;
ConfirmService.OnOpenEvent -= OnConfirmOpen; ConfirmService.OnOpenEvent -= OnConfirmOpen;
NavigationManager.LocationChanged -= OnLocationChanged;
base.Dispose(disposing); base.Dispose(disposing);
} }

View File

@ -16,9 +16,6 @@ namespace AntDesign
{ {
private const string IdPrefix = "Ant-Design-"; private const string IdPrefix = "Ant-Design-";
[Inject]
private NavigationManager NavigationManager { get; set; }
#region Parameters #region Parameters
#pragma warning disable 1591 #pragma warning disable 1591
@ -397,15 +394,6 @@ namespace AntDesign
#region override #region override
protected override void OnInitialized()
{
NavigationManager.LocationChanged += (object sender, LocationChangedEventArgs e) =>
{
_ = JsInvokeAsync(JSInteropConstants.DestroyAllDialog);
};
}
private bool _hasRendered = false; private bool _hasRendered = false;
/// <summary> /// <summary>

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.Web;
using OneOf; using OneOf;
@ -13,6 +14,9 @@ namespace AntDesign
/// </summary> /// </summary>
public partial class Modal public partial class Modal
{ {
[Inject]
private NavigationManager NavigationManager { get; set; }
#region Parameter #region Parameter
/// <summary> /// <summary>
@ -151,7 +155,6 @@ namespace AntDesign
[Parameter] [Parameter]
public bool Visible { get; set; } public bool Visible { get; set; }
/// <summary> /// <summary>
/// Specify a function invoke when the modal dialog is visible or not /// Specify a function invoke when the modal dialog is visible or not
/// </summary> /// </summary>
@ -366,6 +369,8 @@ namespace AntDesign
private bool _hasFocus = false; private bool _hasFocus = false;
private bool _firstShow = true;
private async Task OnAfterDialogShow() private async Task OnAfterDialogShow()
{ {
if (!_hasFocus) if (!_hasFocus)
@ -377,6 +382,32 @@ namespace AntDesign
await ModalRef.OnOpen(); await ModalRef.OnOpen();
} }
} }
if (_firstShow)
{
_firstShow = false;
NavigationManager.LocationChanged += OnLocationChanged;
}
}
private void OnLocationChanged(object sender, LocationChangedEventArgs e)
{
// Modal create by Service
if (ModalRef != null)
{
return;
}
// Modal has been destroyed
if (!Visible && DestroyOnClose)
{
return;
}
if (_dialogWrapper.Dialog != null)
{
_ = JsInvokeAsync(JSInteropConstants.DelElementFrom, "#" + _dialogWrapper.Dialog.Id, GetContainer);
NavigationManager.LocationChanged -= OnLocationChanged;
}
} }
private async Task OnAfterHide() private async Task OnAfterHide()
@ -390,6 +421,7 @@ namespace AntDesign
private async Task OnBeforeDialogWrapperDestroy() private async Task OnBeforeDialogWrapperDestroy()
{ {
NavigationManager.LocationChanged -= OnLocationChanged;
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
} }

View File

@ -11,6 +11,9 @@ namespace AntDesign
[Inject] [Inject]
private ModalService ModalService { get; set; } private ModalService ModalService { get; set; }
[Inject]
private NavigationManager NavigationManager { get; set; }
private readonly List<ModalRef> _modalRefs = new List<ModalRef>(); private readonly List<ModalRef> _modalRefs = new List<ModalRef>();
protected override void OnInitialized() protected override void OnInitialized()
@ -18,6 +21,14 @@ namespace AntDesign
ModalService.OnModalOpenEvent += ModalService_OnModalOpenEvent; ModalService.OnModalOpenEvent += ModalService_OnModalOpenEvent;
ModalService.OnModalCloseEvent += ModalService_OnModalCloseEvent; ModalService.OnModalCloseEvent += ModalService_OnModalCloseEvent;
ModalService.OnModalUpdateEvent += ModalService_OnModalUpdateEvent; ModalService.OnModalUpdateEvent += ModalService_OnModalUpdateEvent;
NavigationManager.LocationChanged += OnLocationChanged;
}
private void OnLocationChanged(object sender, EventArgs e)
{
_modalRefs.Clear();
InvokeStateHasChanged();
} }
private async Task ModalService_OnModalOpenEvent(ModalRef modalRef) private async Task ModalService_OnModalOpenEvent(ModalRef modalRef)
@ -56,6 +67,7 @@ namespace AntDesign
ModalService.OnModalOpenEvent -= ModalService_OnModalOpenEvent; ModalService.OnModalOpenEvent -= ModalService_OnModalOpenEvent;
ModalService.OnModalCloseEvent -= ModalService_OnModalCloseEvent; ModalService.OnModalCloseEvent -= ModalService_OnModalCloseEvent;
ModalService.OnModalUpdateEvent -= ModalService_OnModalUpdateEvent; ModalService.OnModalUpdateEvent -= ModalService_OnModalUpdateEvent;
NavigationManager.LocationChanged -= OnLocationChanged;
base.Dispose(disposing); base.Dispose(disposing);
} }

View File

@ -27,7 +27,8 @@
"build:doc": "gulp build:preview --max-old-space-size=81920", "build:doc": "gulp build:preview --max-old-space-size=81920",
"preinstall": "dotnet tool restore", "preinstall": "dotnet tool restore",
"changelog": "node ./scripts/print-changelog", "changelog": "node ./scripts/print-changelog",
"lint": "eslint ./components --ext .ts" "lint": "eslint --ext .ts ./components",
"lint-fix": "eslint --fix --ext .ts ./components"
}, },
"devDependencies": { "devDependencies": {
"@ant-design/colors": "^6.0.0", "@ant-design/colors": "^6.0.0",