使用未保存的更改阻止更改页面

时间:2018-05-14 18:13:57

标签: javascript jquery reactjs

让我解释一下我想要实现的目标:首先,我要构建一个React应用程序,但我认为这是一个与JavaScript相关的问题"。

基本上,我想要的是阻止用户在对表单进行一些更改时更改页面并且他没有保存它们。为此,我们假设我们有一个变量formIsEdited,如果有未保存的更改,则设置为true,否则为false

我知道使用beforeUnload事件或属于反应路由器的<Prompt>组件可以实现与此类似的功能,但两者都不允许我拥有自定义模式:我希望用自己的风格,我自己的按钮等来展示它,...

所以,我提出了一个想法:我在eventListener事件上添加了click,如果点击是在链接上并且formIsEdited为真:

  1. 我阻止了默认行为;
  2. 我保存了变量lastClick点击的元素;
  3. 我展示了我的模态;
  4. 如果用户选择继续更改页面,我将formIsEdited设置为false,我假装点击保存在lastClick中的元素,该元素将指向更改页面。
  5. 然后,整个div可能会出现在anchor元素中,所以我还需要找到最近的anchor元素,在该元素上进行点击:如果链接的研究没有返回null,则表示点击会引导我链接。所以,我猜测e.stopPropagation()会实现我想要的,但......它没有!

    如果你看一下片段代码..我想,如果你点击蓝色框,$(e.target).closest('a');会找到stackOverflow的链接然后,因为它不是null,会停止传播,因此会避免更改页面..但它不起作用。

    知道为什么吗?或者想要实现我想要的第一个想法?

    编辑:我知道还有其他几个关于阻止changePage的问题,但这个问题更多的是stopPropagation无法避免点击anchor的原因元件。

    还有一个信息:如果我将document.anchors和foreach元素添加一个监听器,我在其中执行我之前逐项列出的操作,我可以使用自己的模态和我自己的逻辑来阻止更改页面! 但是,不幸的是,由于我使用了React,当我可以调用添加刚刚提到的监听器的函数时,某些anchor项不在DOM中。

    EDIT2:我尝试过Luca的解决方案,正如我记得的那样,它并没有起作用。但是React的行为很奇怪&#34;。

    让我解释一下:如果我使用以下代码:     let anchors = document.getElementsByTagName(&#34; a&#34;);

    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();
    }
    

    事情有效。实际上,让我们假装点击链接到/帐户页面的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();
        }
    }
    

    看来要打印的第一件事是Account组件构造函数中的console.log,然后是inside function 2

    我不知道,似乎如果我直接修改锚的行为,我实际上可以重定向/更改点击链接所执行操作的流程。相反,通过修改点击事件的行为,我不能..但似乎现在这个事实更多与React相关,因为在这里的片段中e.preventDefault()有效。

    &#13;
    &#13;
    window.addEventListener("click", (e) => {
      var closestLink = $(e.target).closest('a');
      if (closestLink!= null) {
          e.preventDefault();
          e.stopPropagation();
        }
    });
    &#13;
    #span-1, #span-2 {
      display: inline-block;
      width: 200px;
      height: 100px;
    }
    
    #span-1 {
      background-color: blue;
    }
    
    #span-2 {
      background-color: green;
    }
    &#13;
    <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>
    &#13;
    &#13;
    &#13;

1 个答案:

答案 0 :(得分:1)

我建议使用preventDefault()代替stopPropagation(),请阅读What's the difference between event.stopPropagation and event.preventDefault?以获取有关该主题的更多信息。

&#13;
&#13;
window.addEventListener("click", (e) => {
  var closestLink = $(e.target).closest('a');
  if (closestLink!= null) {
    e.preventDefault();
    }
});
&#13;
#span-1, #span-2 {
  display: inline-block;
  width: 200px;
  height: 100px;
}

#span-1 {
  background-color: blue;
}

#span-2 {
  background-color: green;
}
&#13;
<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>
&#13;
&#13;
&#13;

这仍然只适用于DOM中的链接,您无法通过任何其他操作控制用户离开,例如单击书签栏中的链接或使用单击处理程序更改或替换位置的元素。