React自定义iframe中ref作用、props使用等技术疑问
两段React组件代码
1. MyComponent组件
import React from 'react' function MyComponent() { return ( <div> <p style={{color: 'red'}}>Testing to see if my component renders!</p> </div> ) } export default MyComponent;
2. CustomIframe组件
import React, { useState } from 'react' import { createPortal } from 'react-dom' const CustomIframe = ({ children, ...props }) => { const [contentRef, setContentRef] = useState(null) const mountNode = contentRef?.contentWindow?.document?.body return ( <iframe {...props} ref={setContentRef}> {mountNode && createPortal(children, mountNode)} </iframe> ) } export default CustomIframe;
技术问题解答
先补充:React中ref属性的基础说明
React里的ref属性是用来获取真实DOM元素或者类组件实例的手段。给DOM标签加ref,就能拿到这个DOM节点的引用;给类组件加ref,能拿到组件实例。它的作用是绕开React的声明式渲染,直接操作DOM或组件实例,比如获取DOM尺寸、操作表单值,或是像这里一样获取iframe的内部窗口对象。
你之前了解的useRef是Hook的一种,用来创建保存可变值的容器,组件重渲染时这个值不会重置。但ref属性是DOM元素/组件上的专属属性,用来绑定引用,它可接受三种类型的值:
- 字符串(已废弃,不推荐使用)
- 回调函数:比如代码里的
setContentRef,React会在DOM挂载后把DOM节点作为参数传给这个函数,卸载时传null useRef或createRef创建的ref对象:React会把DOM节点赋值给该对象的.current属性
问题1:return中的ref属性作用是什么?为什么需要它?为什么要传入setContentRef而非contentRef?
- ref属性的作用:这里的
ref={setContentRef}是用来获取<iframe>真实DOM元素的引用,并把这个引用存到contentRef状态里。 - 为什么需要它:要往iframe内部渲染内容,必须拿到iframe的
contentWindow.document.body(即iframe内部文档的body节点),而要获取这个对象,首先得拿到iframe本身的DOM引用,所以需要ref来获取该节点。 - 为什么传setContentRef而非contentRef:因为这里用的是回调式ref。React在DOM元素挂载完成后,会自动把DOM节点作为参数调用这个回调函数,
setContentRef是状态更新函数,调用它就能把DOM节点存到contentRef里。如果直接传contentRef(当前的状态值),只是把null传给ref属性,根本没法更新引用——因为状态是只读的,必须用setter函数才能更新。而且回调式ref能保证每次DOM更新时都拿到最新节点,使用更灵活。
问题2:iframe标签中使用{...props}的原因是什么,这些props并未在其他地方被消费?
这里的{...props}是把父组件传给CustomIframe的所有额外props(除了已解构的children),直接透传给底层的<iframe>DOM元素。比如父组件用<CustomIframe width="800" height="600" src="some-url" />,这些width、height、src就会直接成为<iframe>的原生属性。
这些props看起来没在组件内部消费,是因为它们本来就是给原生iframe用的,不需要在CustomIframe里额外处理。透传后,iframe就能拥有这些属性对应的功能,比如设置尺寸、加载指定地址等,让CustomIframe组件更通用,父组件可以根据需求传递任何iframe支持的原生属性。
内容的提问来源于stack exchange,提问作者Anjali Chauhan
相关产品推荐
相关产品推荐

