Refs & DOM

Refs 提供了一种方式,用于访问在 render 方法中创建的 DOM 节点或 React 元素.

在典型的 React 数据流中,属性(props)是父组件与子组件交互的唯一方式. 要修改子组件,需要使用新的 props 重新渲染他, 但是某些情况下需要典型数据流外强制修改子组件. 要修改的子组件可以是 React 组件的实例, 也可以是 DOM 元素.

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

  • 处理焦点,文本选择或媒体控制
  • 触发强制动画
  • 集成第三方 DOM 库
    如果可以通过声明式实现, 则尽量避免使用 refs.

避免过度使用 Refs:
你可能首先会想到在你的应用程序中使用 refs 来更新组件, 如果是这种情况,请花一点时间,重新思考一下 state 属性在组件层中位置. 通常会明白,提升state 所在的组件层级会是更合适的做法.

创建 Refs
使用 React.createRef() 创建refs, 通过 ref属性来获取 React 元素. 当构造组件时, refs 通常被赋值给实例的一个属性,这样你可以在组件中任意一处使用它们.

class MyComponent extends React.Component {
	constructor (props) {
		super (props);
		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() 将接收底层DOM 元素作为他的 current 属性以创建 ref.
  • 当 ref 属性被用于一个自定义类组件时, ref 对象将接收该组件已挂载的实例作为他的 current.
  • 不能在函数式组件上使用 ref 属性, 因为他们没有实例

为 DOM 元素添加 Ref
使用 ref 存储对DOM 节点的引用:

class CustomTextInput extends React.Component {
	constructior(props) {
		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>
		)
	}
}

react 会在组件加载时将 DOM 元素传入 current 属性, 在卸载时则会改回 null. ref 的更新会发生在 componentDidMount 或 componentDidUpdate 生命周期钩子之前.

为类组件添加 Ref:
如果我们想要包装上面的 CustomTextInput , 来模拟挂载之后立即被点击的话, 我们可以使用 ref来访问自定义输入,并手动调用它的 focusTextxInput方法:

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

需要注意的是,这种方法仅对 class 声明的 CustomTextInput 有效.

Refs 与函数式组件:
不能在函数式组件上使用 ref 属性,因为他们没有实例.
如果想使用 ref , 就像你想使用生命周期方法或者 state 一样,应该将其转化为 class 组件.
但是,你可以在函数式组件内部使用 ref, 只要他指向一个 DOM 元素或class 组件.

function CustomTextInput (props) {
	//这里必须声明 textInput ,这样 ref 回调才可以引用他
	let textInput = null;
	function handleClick() {
		textInput.focus();
	}
	return (
		<div>
			<input  type="'text" ref={ (input) => { textInput = input; }} />
			<input type="button" value="Focus the teaxt input"  onClick={ handleClick } />
		</div>
	)
}

回调 Refs:
react 也支持另一种设置 ref 的方式,称为"回调 ref",更加细致的控制何时 ref 被设置和解除.
不同于传递createRef() 创建的 ref 属性,你会传递一个函数. 这个函数接受 react 组件的实例或 HTML DOM 元素作为参数,以存储他们并使他们能被其他地方访问.

下面的例子描述了一种通用的范例: 使用 ref回调函数,在实例的属性中存储对 DOM 节点的引用.

class CustomTextInput extends React.Component {
	constructor(props) {
		super(props);
		this.textInput = null;
		this.setTextInputRef = element => {
			this.textInput = element;
		};
		this.focusTextInput = () => {
			//直接使用原生 API 使 text 输入框获得焦点
			if (this.textInput) this.textInput.focus();
		};
	}
	componentDidMount() {
		//渲染后文本框自动获得焦点
		this.focusTextInput();
	}
	render() {
		//使用 ref 的回调将 text 输入框的 DOM 节点存储到 React
		//实例上 (比如: this.textInput)
		return (
			<div>
				<input type="text" ref={ this.setTextInputRef } />
				<input type="button" value="Focus the text input"  onClick={ this.focusTextInput } />
			</div>
		);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值