Refs & DOM (React)

React中的Refs提供了一种访问DOM节点或React元素的方式,适用于管理焦点、动画、集成第三方库等场景。通常,避免过度使用Refs,而是通过state进行数据流动。创建Refs使用React.createRef(),并可通过ref属性附加到元素。回调Refs则允许更细粒度地控制何时设置和清除引用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Refs and the DOM

Refs 提供了一种方式,允许我们访问DOM节点火灾render 方法中创建的React 元素。
在典型的 React 数据流中,props 是父组件于子组件交互的唯一方式。要修改一个子组件,你需要使用新的props来重新渲染它。但是,在某些情况下,你需要在典型数据流之外强制修改子组件。被修改的子组件可能是一个 React 组件的实例,也可能是一个 DOM 元素。对于这两种情况,React 都提供了解决办法。

什么时候使用 Refs

下面是几个适合使用 refs 的情况:

  • 管理焦点,文本选择或媒体播放。
  • 触发强制动画。
  • 集成第三方 DOM 库。

避免使用 refs 来做任何可以通过声明式实现来完成的事情。
举个例子,避免在 Dialog 组件里暴露 open()和 close()方法,最好传递 isOpen 属性。

不要过度使用 Refs

你可能首先会想到使用 refs 在你的 app 中 “让事情发生” 如果是这种情况,考虑一下 state 属性应该被安排在那个组件层。通常情况下,让更高的组件层级拥有这个 state ,是更恰当的。

创建 Refs

Refs 是使用 React.createRef() 创建的,并通过 ref 属性附加到 React 元素。在构造组件时,通常将 Refs 分配给实例属性,以便可以在整个组件中引用它们。

class MyComponent extends React.Component {
	constructor(props) {
		super(porps);
		this.myRef = React.createRef();
	}
	render() {
		return <div ref={this.myRef} />;
	}
}
访问 Refs

当 ref 被传递给 render 中的元素时,对该节点的引用可以在 ref 的 current 属性中被访问。
const node = this.myRef.current;
ref 的值根据节点的类型而有所不同:

  • ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的ref 接受底层 DOM 元素作为 current 属性。
  • ref属性用于自定义 class 组件时,ref 对象接受组件的挂载实例作为其 current 属性。
  • 你不能在函数组件上使用 ref 属性,因为他们没有实例。
为 DOM 元素添加 ref

使用 ref 去存储 DOM 节点的引用:

class CustomTextInput extends React.Component {
	constructor(porps){
		super(props);
		//创建一个 ref 来存储 textInput 的 DOM 元素
		this.textInput = React.createRef();
		this.focusTextInput = this.focusTextInput.bind(this);
	}
	focusTextInput() {
		//直接使用原生 API 使 text 输入框获得焦点
		//注意:我们通过 “current” 来访问 DOM 节点
		this.textInput.current.focus();
	}
	render() {
		//告诉 React 我们想吧 <input> ref 关联到
		//构造器里创建的 ‘textInput’ 上
		return(
			<div>
				<input
					type="text"
					ref={this.textInput} 
				/>
				<input
					type="button"
					value="Focus the text input"
					onclick={this.focusTextInput}
				/>
			</div>
		);
	}
}

通过current可以直接访问 DOM 元素。
React 会在组件挂载时给 current 属性传入 DOM 元素,并在组件卸载时传入 null 值。ref 会在 componentDidMount 或 componentDidUpdate 生命周期钩子触发前更新。

为class组件添加 Ref

如果我们想包装上面的 CustomTextInput ,来模拟它挂载之后立即被点击的操作,我们可以使用 ref 来获取这个自定义的 input 组件并手动调用它的 focusTextInput 方法:

class AutoFocusTextInput extends React.Component {
	constructor(porps){
		super(props);
		this.textInput  = React.createRef();
	}	
	componentDidMount(){
		this.textInput.current.focusTextInput();	
	}
	render() {
		return (
			<CustomTextInput ref={this.textInput} />	
		);
	}
}

仅在 CustomTextInput 声明为 class 时才有效:

class CustomTextInput extends React.Component {
	// ...
}

Refs 与函数组件

你不能在函数组件上使用 ref 属性,因为它们没有实例:

function MyFunctionComponent () {
	return <input />;
}
class  Parent extends React.Component {
	constryctor(props) {
	super(porps);
	this.textInput = React.createRef();	
	}
	render() {
		// This will "not" work!
		return (
			<MyFinctionComponent ref={this.textInput} />	
		);	
	}
}

如果你需要使用 ref ,你应该将组件转化为一个 class ,就像当你需要使用生命周期钩子或 state 时一样。

不管怎样,你可以在函数组件内部使用 ref 属性,只要它指向一个 DOM 元素或 class 组件:

function CustomTextInput (porps){
	// 这里必须声明 textInput ,这样 ref 才可以引用它
	let textInput = React。createRef();
	function handleClick() {
		textInput.current.focus();
	}
	return(
		<div>
			<input
				type="text"
				ref={textInput} />
			<input
				type="button"
				value="Focus the text input"
				onclick={handleClick} 
			/>	
		</div>
	);
}
回调 Refs

React 也支持另一种设置 refs 的方式,称为”回调 refs“。他能助你更细的控制何时 refs 被设计和解除。

不同于传递 createRef() 创建的 ref 属性,你会传递一个函数。这个函数中接受 React 组件实例或 HTML DOM元素作为参数,以时它们能在其他地方被存储和访问。

class CustomTextInput extends React.Component {
	constructor(porps){
		super(props);
		this.textInput = null;
		this.setTextInputRef = element =>{
			this.textInput = element;
		};
			
		this.focusTextInput= () =>{
			//使用原生 DOM API 使 text 输入框获得焦点
			if(this.textInput) this.textInput.focus();	
		};	
	}
	
	componentDidMount() {
		//组件挂载后,让文本框自动获得焦点
		this.focusTextInput();	
	}
	render(){
		// 使用 ‘ref’ 的回调函数将 text 输入框 DOM 节点的引用存储到 React
		return(
			<div>
				<input
					type="text"
					ref={this.setTextInputRef} 
				/>
				<input
					type="button"
					value="Focus the text input"
					onClick={this.focusTextInput} 
				/>
			</div>	
		);
	}
}

React 将在组件挂载时,会调用 ref 回调函数并传入 DOM 元素,当卸载时调用它并传入 null。在 componentDidMount 或 componentDidUpdate 触发前,React 会保证 refs 一定是最新的。

可以在组件间传递回调形式的 refs。

function CustomTextInput(porps) {
	return(
		<div>
			<input ref={props.inputRef} />
		</div>	
	);
}
class Parent extends React.Component {
	render() {
		return(
			<CustomTextInput
				inputRef={el => this.inputElement = el}
			/>
		);	
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值