让我解释一下我想要实现的目标:首先,我正在构建一个 React 应用程序,但我认为这是一个与 JavaScript 相关的"问题"。
基本上,我想要的是防止用户在对表单进行一些更改并且没有保存它们时更改页面。为此,让我们假设我们有一个变量formIsEdited
设置为true
是否有未保存的更改,否则false
。
我知道可以通过beforeUnload
事件或属于 React Router 的<Prompt>
组件来实现类似的事情,但两者都不允许我拥有自定义模态:我想显示的是一个具有我自己的风格、我自己的按钮等的div,......
所以,我想出了一个主意:我在click
事件上放了一个eventListener
,如果点击是链接并且formIsEdited
是真的:
- 我阻止默认行为;
- 我保存在一个变量中,
lastClick
单击元素; - 我展示我的模态;
- 如果用户选择处理更改页面,我将
formIsEdited
设置为 false,我假装单击保存在lastClick
中的元素,这将导致更改页面。
然后,可能会发生整个div
都在anchor
元素内,所以我还需要找到点击的div 中最接近的anchor
元素:如果对链接的研究没有返回null
,这意味着点击会将我引导到一个链接。所以,我猜e.stopPropagation()
会实现我想要的,但是......没有!
如果你看一下代码片段..我认为,如果您单击蓝色框,$(e.target).closest('a');
会找到指向stackOverflow的链接,然后,由于它不为空,因此会停止传播,因此会避免更改页面。但它不起作用。
知道为什么吗?或者有什么想法可以实现我最初想要的东西吗?
编辑:我知道还有其他几个关于防止更改页面的问题,但这个问题更多的是关于stopPropagation
不避免单击anchor
元素的原因。
还有一个信息:如果我采用document.anchors
foreach 元素添加一个侦听器,在其中执行我之前逐项列出的操作,我可以用我自己的模态和我自己的逻辑阻止更改页面! 但是,不幸的是,由于我使用的是 React,当我可以调用添加刚才提到的侦听器的函数时,某些anchor
项不在 DOM 中。
编辑2:我尝试了卢卡的解决方案,但我记得,它不起作用。但是 React 的行为是"奇怪的"。
让我解释一下:如果我使用以下代码: let anchors = document.getElementsByTagName("a"(;
for (let i = 0; i < anchors.length; i++) {
anchors[i].addEventListener("click", (e) => {
clickListenerAnchorUnsavedChanges.call(this, e, anchors[i]);
}
}
function clickListenerAnchorUnsavedChanges(this: any, e: any, anchor: any) {
// if Edit has been made
console.log("Inside function1");
e.preventDefault();
}
这些东西有效。实际上,让我们假设我单击链接到/Account 页面的anchor
:写入inside function1
在我放入组件帐户的构造函数中的写入之前打印。
相反,具有以下功能:
function test1(this: any) {
window.addEventListener("click", (e) => {
console.log("inside function 2");
// if edits have been made
let closestLink = $(e.target).closest('a');
if (closestLink != null) e.preventDefault();
}
}
似乎首先要打印的是控制台.log在 Account 组件的构造函数中,然后是inside function 2
。
我不知道,似乎如果我直接修改锚点的行为,我实际上可以通过单击链接来重定向/更改操作的流程。相反,通过修改点击事件的行为,我不能。但现在看来这个事实与 React 更相关,因为在这里的片段中,e.preventDefault()
有效。
window.addEventListener("click", (e) => {
var closestLink = $(e.target).closest('a');
if (closestLink!= null) {
e.preventDefault();
e.stopPropagation();
}
});
#span-1, #span-2 {
display: inline-block;
width: 200px;
height: 100px;
}
#span-1 {
background-color: blue;
}
#span-2 {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<a href="https://stackoverflow.com/">
<span id="span-1" />
</a>
<span id="span-2">
</span>
</div>
我建议使用preventDefault()
而不是stopPropagation()
,请阅读event.stopPropagation和event.preventDefault有什么区别?以获取有关该主题的更多信息。
window.addEventListener("click", (e) => {
var closestLink = $(e.target).closest('a');
if (closestLink!= null) {
e.preventDefault();
}
});
#span-1, #span-2 {
display: inline-block;
width: 200px;
height: 100px;
}
#span-1 {
background-color: blue;
}
#span-2 {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<a href="https://stackoverflow.com/">
<span id="span-1"></span>
</a>
<span id="span-2">
</span>
</div>
这仍然仅适用于 DOM 中的链接,您无法通过任何其他操作控制用户移开,例如单击书签栏中的链接或使用单击处理程序更改或替换位置的元素。