React - 如何在回收合成事件之前触发 preventDefault()?

IT技术 reactjs preventdefault
2021-05-03 07:43:00

我在单击链接时运行的 React 组件中具有以下功能:

onClick(e, { name }) {
    e.stopPropagation();

    const doIt = await checkSomething();

    if (doIt) {
        e.preventDefault();
        doSomethingElse();
    }
}

问题是e.preventDefault()到达时合成事件被回收。那么,当需要一些逻辑来计算这个决定时,以及在合成事件被回收之前,我如何告诉浏览器在点击链接时不要跟随它?

4个回答

处理此问题的一种方法是使用preventDefault,当操作完成并且您需要路由时,使用自己调用路由逻辑history.push()

onClick(e, { name }) {
    e.stopPropagation();
    e.preventDefault();
    const doIt = await checkSomething();

    if (doIt) {
        doSomethingElse();
    } else {
        this.props.history.push('/pathToRoute');
    }
}

检查有关如何使用 React-router 以编程方式导航的答案

我只是在这里提出一个想法。

如果您不能或不想以编程方式进行 URL 重定向,那么还有另一种选择。
您可以嵌套一个函数(柯里化)并仅在完成逻辑后调用第二个函数。
请注意,这将要求您将嵌套函数编写为IIFE


这是使用 JavaScript(打开控制台)的一个小概念证明:

const el = document.getElementById("link");


function onLinkClick() {
  console.log('doing some stuff..');
  for(let i = 0; i < 500; i++){
  	console.log(`doing more stuff #${i}`);  
  }
  return function(e) {
    // this will trigger with the actuall event (note this is an IIFE)
    console.clear();
  }();
}

el.addEventListener('click', onLinkClick);
#big {
  min-height: 950px;
}
<div id="big">
  <a id="link" href="#test">Click to get to the bottom of the page</a>
</div>

<div id="test">Bottom of page</div>


react示例:

class App extends React.Component {

  onClick = (e) => {
    console.log('doing some stuff..');
    for (let i = 0; i < 500; i++) {
      console.log(`doing more stuff #${i}`);
    }
    return ((e) => {
      //console.log(e, "inner function")
      console.clear();
    })(e)
  }

  render() {
    return (
      <div>
        <div style={{ height: '950px' }}>
          <a href="#test" onClick={this.onClick} >Click to get to the bottom of the page</a>
        </div>

        <div id="test">Bottom of page</div>
      </div>
    );
  }
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

preventDefault在事件上使用,您需要在回调函数返回之前执行此操作。这不是异步任务完成后可以做的事情。

如果您查看MDN Event.preventDefault Notes,您会注意到它说您必须在事件流中的某处调用它。

在事件流的任何阶段调用 preventDefault() 都会取消事件,这意味着实现通常作为事件结果采取的任何默认操作都不会发生。

你也可以参考这个问题:event.preventDefault in async functions 在最上面的答案中,您会看到在第一个语句之前提到了使用awaitevent.preventDefault()需要如何发生await这适用于使用 Promise 或任何异步操作。

作为旁白:

如果您想以异步方式访问事件属性,您应该对事件调用 event.persist(),这将从池中删除合成事件并允许用户代码保留对事件的引用。

这是SyntheticEvent 文档

您是否尝试过使用 Promise 和 .then():

// Async/Await
const asyncGreeting = async () => 'Greetings';

// Promises
const promiseGreeting = () => new Promise(((resolve) => {
  resolve('Greetings');
}));

asyncGreeting().then(result => console.log(result));
promiseGreeting().then(result => console.log(result));

您应该能够控制 preventDefault();