当前位置: 首页 > Web前端 > HTML

React源码阅读-2_031

时间:2023-04-02 14:53:07 HTML

React源码阅读-2在典型的React数据流中,props是父组件与其子组件交互的唯一方式。要修改子项,请使用新道具重新渲染它。但是,在某些情况下,有必要在典型数据流之外强制修改子项。要修改的子项可以是React组件或DOM元素的实例。对于这两种情况,React都提供了API。何时使用refsrefs有一些很好的用例:1.文本选择或媒体播放。2.触发命令式动画。3.与第三方DOM库集成。避免将refs用于任何可以声明式完成的事情。不要过度使用Refs遗留API:字符串引用如果您以前使用过React,您可能熟悉旧API,其中ref属性是字符串textInput,DOM节点作为this.refs.textInput访问。建议不要使用它,因为字符串引用有一些问题并且被认为是遗留的并且可能会在未来的某个版本中被删除。回调refReact会在组件挂载时调用带有DOM元素的ref回调,在组件卸载时调用null。在componentDidMount或componentDidUpdate触发之前,保证Refs是最新的。classCustomTextInputextendsReact.Component{constructor(props){super(props);this.textInput=null;this.focusTextInput=()=>{//使用原始DOMAPI聚焦文本输入if(this.textInput)this.textInput.focus();};}componentDidMount(){//将输入自动聚焦到挂载上this.focusTextInput();}render(){//使用`ref`回调将对文本输入DOM//元素的引用存储在实例字段中(例如,this.textInput)。return(

this.textInput=element}/>
);}}回调refs注意事项如果ref回调函数是方法定义的内联函数,在update过程中会执行两次,第一次传入参数null,第二次传入参数DOM元素在。这是因为在每次渲染时都会创建该函数的一个新实例,因此React会清除旧的ref并设置新的。将ref回调函数定义为类的绑定函数可以避免上述问题,但在大多数情况下是无关紧要的。refsexample--clicktogetinputfocusclassExampleextendsReact.Component{handleClick(){//使用原生DOMAPI获取焦点}render(){//当组件被插入DOM最后,ref属性添加一个组件引用到this.refsreturn(
);使用React16.3中引入的React.createRef()React.createRef()API。如果您使用的是早期版本的React,我们建议您使用回调引用。创建React.createRef()引用是使用React.createRef()属性创建的,并通过ref属性附加到React元素。在构建组件时,通常将Refs分配给实例属性,以便它们可以在整个组件中被引用。类MyComponent扩展React.Component{constructor(props){super(props);this.myRef=React.createRef();}render(){return;}}访问引用当ref传递给元素渲染时,对节点的引用在currentref属性constnode=this.myRef.current;当React.createRef()接收底层DOM元素作为其当前属性时,在构造函数中创建的refHTML元素ref属性上使用此属性时,ref的值会根据节点类型而变化。在ref自定义类组件上使用此属性时,ref对象将接收组件的已安装实例作为其当前实例。您可能无法引用功能组件上的属性,因为它们没有实例。类CustomTextInput扩展React.Component{constructor(props){super(props);//创建一个ref来存储textInputDOM元素this.textInput=React.createRef();this.focusTextInput=this.focusTextInput.bind(this);}focusTextInput(){//使用原始DOMAPI显式聚焦文本输入//注意:我们正在访问“current”以获取DOM节点this.textInput.current.focus();}render(){//告诉React我们想要将ref//与我们在构造函数中创建的`textInput`相关联return(
);}}React将在组件挂载时分配给此属性的当前DOM元素,并在卸载时返回null。ref更新发生在componentDidMount或componentDidUpdate生命周期方法之前。源代码//具有单个可变值导出函数的不可变对象createRef():RefObject{constrefObject={current:null,};如果(__DEV__){Object.seal(refObject);}returnrefObject;}不能在函数组件中引用在functionMyFunctionComponent()上使用这个属性{return;}classParentextendsReact.Component{constructor(props){super(props);this.textInput=React.createRef();}render(){//这不会*行得通!返回();}}**如果您需要引用它,您应该将您的组件转换为一个类,就像您需要生命周期方法或状态一样。但是,ref属性可以在函数组件中使用,只要它引用DOM元素或类组件即可:创建引用();函数handleClick(){textInput.current.focus();}return(
);}暴露对父组件的DOM引用在极少数情况下,可能需要从父组件访问子组件的DOM节点。通常不推荐这样做,因为它会破坏组件封装,但它偶尔可以用于触发焦点或测量子DOM节点的大小或位置。虽然可以添加对子组件的引用,但这不是一个理想的解决方案,因为只有组件实例可用,而没有DOM节点。此外,这不适用于功能组件。如果您使用的是React16.3或更高版本,我们建议在这些情况下使用ref转发。引用转发允许组件选择将任何子组件的引用公开为它自己的组件。有关如何将子DOM节点暴露给父组件的详细示例,请参见引用转发文档。如果您使用的是React16.2或更低版本,或者您需要比ref转发提供更多的灵活性,您可以使用此解决方法并显式地将ref作为具有不同名称的prop传递。建议尽可能不要公开DOM节点,但这可能是一个有用的逃生通道。请注意,此方法需要您向子组件添加一些代码。如果您完全无法控制子组件的实现,最后一个选择是使用findDOMNode(),但不鼓励使用StrictMode。

猜你喜欢