【问题标题】:How to edit a recieved JSX element to attach a prop to any img element inside it?如何编辑收到的 JSX 元素以将道具附加到其中的任何 img 元素?
【发布时间】:2019-10-04 11:37:35
【问题描述】:

我希望能够将 onLoad/onAbort 属性添加到传递给我的函数的 JSX 元素内的任何图像或视频元素。

我正在创建一个画廊组件,它接受 JSX 元素并以选定的模式显示它们。这个想法是可以传入任何 JSX 元素,并将其格式化和显示。为了使其正常工作,尤其是执行多次传递的排序算法,我需要知道图像和视频何时加载并采用其原始分辨率,以便我可以缩放它们并保留比率。为此,我想将 onload 和 onabort 属性附加到传递给我的函数的 JSX 元素中包含的每个图像,该函数更新我的组件状态,告诉组件图像已加载。

我不知道怎么做,因为传入的 JSX 元素的结构没有限制。它可以具有任何级别的嵌套,并且图像或视频可以位于该结构内的任何位置。如果我在渲染后这样做,我会这样做:

   //gridRef.current is the grid element ref I get through useRef()
   const images = gridRef.current.querySelectorAll('img');
   images.forEach((image, index) => {
      if (image.complete) //mark current image as already loaded
      else {
         image.onload = () => {
            //mark current image as loaded after it loads
         };
         image.onabort = () => {
            //mark current image as loaded after it aborts
         };
         image.onerror = () => {
            //mark current image as loaded after it errors out
         };
         //mark current image as not loaded yet
      }
   });

视频也是如此。不过,我不想在渲染后执行此操作,因为图像可能会在 image.complete 检查之后和附加侦听器之前加载,这会导致错误。在渲染元素之前这样做会更自然,但是如何?

我想要以下之一:

1) 类似于 image.complete 属性的东西,它告诉我是否加载了所有后代元素,所以如果我在我的网格元素上使用它,它只会在所有后代节点中的所有图像都加载后才返回 true。然后我可以在渲染后执行此检查,而无需编辑 JSX。

2) 一种搜索 JSX 元素层次结构并检索然后编辑所有 img 和 video 元素的方法。

3) 当所有子组件都已加载时触发函数的属性。

4) 实现相同目标的任何其他东西。

【问题讨论】:

    标签: javascript html reactjs jsx


    【解决方案1】:

    我目前正在使用的一个解决方案是只使用一个递归超时来查看由

    获取的所有图像
       const images = gridRef.current.querySelectorAll('img');
    

    并检查 image.complete 的每一个,如果它们都是真的,它会调用我的排序函数,如果不是,它会调用它自己并在超时后再次检查。它适用于图像,但 video 元素没有 .complete 属性。

    编辑:视频有一个 .readyState 可以正常工作的道具。

    【讨论】:

      【解决方案2】:

      您可以克隆元素,然后递归地克隆它们的子元素。在根据孩子的类型克隆孩子之前添加您想要的道具,以便以后期渲染的方式进行。 函数示例:

      function editJSX(Component, newProps = {}) {  
        return React.cloneElement(Component, newProps, React.Children.map(Component.props.children, c => {
          let myProps = {};
          if(c.type === "img") {      
            myProps =  {onLoad: handleOnLoad};
          }
          return editJSX(c,myProps); // recursion
        }));
      }
      

      检查所有正在加载的图像的完整演示:https://codesandbox.io/embed/bold-lalande-uhymj

      【讨论】:

        猜你喜欢
        • 2020-07-28
        • 1970-01-01
        • 2023-01-16
        • 2015-07-27
        • 2019-10-17
        • 2020-09-02
        • 2014-02-14
        • 2021-04-18
        • 2020-04-17
        相关资源
        最近更新 更多