受控组件与非受控组件(二)

596 阅读2分钟

讲非受控组件之前,我们先理解Refs and the DOM的概念。

Refs and DOM

在React的典型数据流中,props是父子组件的唯一交互方式。要修改子组件,就要通过修改props来重新渲染子组件。而refs属性,则提供了在典型数据流以外,强制修改子组件的方式。被修改的子组件可能是一个DOM元素,也有可能是一个组件React实例。

使用refs属性

通过React.createRef()函数创建一个ref,并通过ref属性附加到React元素上:

class MyComponent extends React.Component {
	constructor(){
		super();
		this.myRef = React.createRef();
  	this.handleClick = this.handleClick.bind(this);
	}
  handleClick(){
    console.log(this.myRef.current)
  }
	render(){
		return <button ref={this.myRef} onClick={this.handleClick}>点击</button>
	}
}

当 ref 被传递给 render 中的元素时,对该节点的引用可以在 ref 的 current 属性中被访问。

const node = this.myRef.current

如果ref属性属于一个HTML元素,则接收底层 DOM 元素作为current属性。

如果ref属性属于一个class组件,ref 对象接收组件的挂载实例作为其 current 属性。

React组件会在挂载的时候给current属性传入DOM元素,并在卸载的时候传入null值。ref 会在 componentDidMountcomponentDidUpdate 生命周期钩子触发前更新。

refs转发

不能在函数组件上使用ref,因为函数组件没有实例。但可以在函数式组件内部使用(使用useRef hook),只要它指向一个DOM或者class组件实例。要想在函数式组件中使用ref属性,可以使用forward ref:

const FancyButton = React.forwardRef((prop, refProp) => {
  return <button ref={refProp}></button>
})
const refForward = React.createRef();
<FancyButton ref={refForward}></FancyButton>

这样通过ref可以访问到button元素,这个FancyButton接收了ref,并向下传递给子组件,就叫ref转发。

refs回调

通过ref回调可以在父组件在访问到子组件。通过给ref属性传入一个函数:

function CustomTextInput(props) {
  return (
    <div>
      <input ref={props.inputRef} /></div>
  );
}

class Parent extends React.Component {
  render() {
    return (
      <CustomTextInput
        inputRef={el => this.inputElement = el} />
    );
  }
}

在这个例子中,我们在父组件中把回调函数以属性的方式传给子组件,子组件把ref属性设置为这个回调函数,这样,父组件的inputElement就指向子组件的input元素了。

参考资料:

React官方文档