【问题标题】:window.addEventListener('load',... not firing on Safari?window.addEventListener('load',... 没有在 Safari 上触发?
【发布时间】:2020-12-24 08:48:20
【问题描述】:

加载后我需要重定向页面并从 URL 获取参数。我可以通过单击按钮来完成。

但我希望自动重定向页面(无需用户输入)。我正在使用window.addEventListener('load', () => handleClick()),它在 Chrome 上运行良好。但在 Safari(桌面版和移动版)上,它并不总是会触发(只是有时会触发 - 并非总是如此)。

我可以通过在处理程序中添加 alert('Beginning'); 来看到这一点 - 在 Chrome 上,这会在页面加载后自动触发,但在 Safari 上不会。

我该如何解决这个问题?

谢谢!

const handleClick = async (event) => {

  alert('Beginning'); //For debugging


  const stripe = await stripePromise;
  const { error } = await stripe.redirectToCheckout({
    param,
  });
}

if (typeof window !== `undefined`) {
const param = new URLSearchParams(window.location.search).get('param');
}

const Page = () => {

  if (typeof window !== `undefined`) {
  window.addEventListener('load', () => handleClick())
  }

  return (
    <section >

      <button role="link" onClick={handleClick}> //Only for fallback
      Press
    </button>

    </section>
  );
};

export default Page;

【问题讨论】:

    标签: javascript html reactjs safari gatsby


    【解决方案1】:

    load 事件可能不太可靠,因为您的组件可能要等到 DOM 加载后才会挂载。相反,您可以使用 React 组件的lifecycle methods 在您的组件安装到页面时做出响应。例如:

    function Component() {
      useEffect(() => alert(1), []);
    
      return (
        <h1>hello world!</h1>
      );
    }
    

    您可以在the documentation 中找到有关效果挂钩的更多信息。将它与空数组一起使用使其类似 componentDidMount() 用于类组件。

    【讨论】:

    • 感谢您的帮助!但是在我使用 useEffect() 之前,它给了我这个问题(见评论和讨论):stackoverflow.com/a/62971266。你如何解释为什么你的解决方案仍然有效?
    • 什么是stripePromise?我无权访问 Stripe 设置,但是在没有真正 API 密钥 this 的情况下使用文档中的一些示例似乎可以正常工作,直到它因未完全设置而引发错误,包括在我的移动 Safari 中iPad。
    【解决方案2】:

    我强烈建议您避免使用window.addEventListenerdocument.addEventListener 等侦听器直接引用DOM。事实上,这就是为什么您使用 React 而不是 jQuery 来创建虚拟 DOM 而不是直接为真实 DOM 充电并降低 Web 性能的原因。

    在 React 中,你有 React hooks 来实现你想要做的事情。它们公开了一堆触发某些事件的生命周期方法。在您的情况下,useEffect 符合您的要求。这个钩子类似于componentDidMount()componentDidUpdate()

    通过使用这个 Hook,你告诉 React 你的组件需要做 渲染后的东西。 React 会记住你传递的函数 (我们将其称为我们的“效果”),稍后再调用它 执行 DOM 更新。在这个效果中,我们设置文档标题, 但我们也可以执行数据获取或调用其他命令 API。

    由于 Strapi 支付和 Safari 移动的需求(需要等待页面加载),我混合了钩子和您的方法,以确保在页面加载时触发效果。

    应用于您的代码:

    const Page = () => {
    
      useEffect(() => {
         if (typeof window !== `undefined`) { window.addEventListener('load', () => handleClick()) }
      }, []);
    
      return (
        <section >
    
          <button role="link" onClick={handleClick}> //Only for fallback
          Press
        </button>
    
        </section>
      );
    };
    
    export default Page;
    

    基本上,一旦加载了 DOM 树,代码将触发 useEffect 函数,并执行您的 handleClick 函数。作为参数传递的空数组([])称为deps;意味着您只触发一次效果。当然,它适用于所有浏览器,因为它是 React 功能。

    【讨论】:

    • 感谢您的帮助!但是在我使用 useEffect() 之前,它给了我这个问题(见评论和讨论):stackoverflow.com/a/62971266。你如何解释为什么你的解决方案仍然有效?
    • 根据该讨论,Safari mobile + Strapi 必须等待页面加载。在这种情况下,我建议混合使用这两种方法。使用useEffect + addEventListener。这将确保 Safari 中的效果始终比您最初的方法更好。
    • 谢谢!所以我可以使用: if (typeof window !== undefined) { window.addEventListener('load', () => handleClick()) } React.useEffect(() => { handleClick(); }, [ ]);
    • 当然可以。如果你将它添加到 useEffect 钩子中,它会在 DOM 加载后触发,并且应该始终做到这一点,而不是像现在这样。
    • 谢谢!那么两者分开应该是最好的吧? window.addEventListener 和 React.useEffect 所以如果一个不触发另一个将触发
    【解决方案3】:

    如果你想在加载页面中触发一个函数并将其重定向到另一个 url,你可以使用这样的自动调用函数

    (function(){
    alert('Beginning');
    if (typeof window !== 'undefined') {
        const param = new URLSearchParams(window.location.search).get('param');
    }
    if (param !== 'undefined' && param !== null $$ param!==[]){
        window.location.href = 'your_new_url_string?param='+param;
    }
    })();
    

    【讨论】:

      猜你喜欢
      • 2020-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多