一、Ref的创建和访问
1、React.createRef()
class MyComponent extends React.Component {
constructor(props) {
super(props)
this.myRef = React.createRef()
}
componentDidMount() {
console.log(this.myRef.current)
}
render() {
return <div ref={this.myRef} />
}
}
2、回调Ref
class MyComponent extends React.Component {
constructor(props) {
super(props)
}
componentDidMount() {
console.log(this.myRef)
}
render() {
return <div ref={el => this.myRef = el} />
}
}
3、useRef(Hook 函数组件写法)
funtion MyComponent() {
const myRef = useRef(null)
useEffect(() => {
console.log(myRef.current)
}, [])
render() {
return <div ref={myRef} />
}
}
二、组件间传递Ref(父组件访问子组件的Ref)
1、回调Ref
父组件将 refs 回调函数当作 inputRef props 传递给了子组件,子组件将相同的函数作为特殊的 ref 属性传递给
<input>标签。父组件中的this.inputElement会被设置为与子组件中的 input 元素相对应的 DOM 节点。
function ChildComp(props) {
return <input ref={props.inputRef} />
}
class ParentComp extends React.Component {
componentDidMount() {
console.log(this.inputElement) // <input />
}
render() {
return <ChildComp inputRef={el => this.inputElement = el}/>
}
}
2、React.forwardRef()
-
父组件通过调用 React.createRef 创建一个 React ref 并将其赋值给 ref 属性。
-
父组件通过 ref 属性向下传递属性
<ChildComp ref={ref}>给子组件。 -
子组件使用 React.forwardRef 包裹,并接受一个函数作为参数,函数参数的第二个为 ref。
-
子组件向下转发该 ref 参数到
<button ref={ref}>。 -
当父组件的 ref 挂载完成,ref.current 将指向子组件的
<button>DOM 节点。
const ChildComp = React.forwardRef((props, ref) => (
<button ref={ref}>
{props.children}
</button>
));
class ParentComp extends React.Component {
constructor(props) {
super(props)
this.buttonRef = React.createRef()
}
componentDidMount() {
console.log(this.buttonRef) // <button />
}
render() {
return <ChildComp ref={this.buttonRef}/>
}
}
3、在使用redux环境下,父组件(class)调用子组件(class)的方法
import React from 'react'
// 父组件
class ParentComp extends React.Component {
onRef = (ref) => {
this.childRef = ref
}
handleChange = () => {
this.childRef.onChangeCount()) // '子组件处理逻辑'
}
render() {
return (
<div>
<button onClick={this.handleChange}>改变子组件的属性</button>
<ChildComp onRef={this.onRef} />
</div>
)
}
}
import React from 'react'
// 子组件
class ChildComp extends React.Component {
state = {
count: 0
}
componentDidMount(){
// 传递子组件实例
this.props.onRef(this)
}
onChangeCount = () => {
// ... other logic
this.setState({ count: this.state.count + 1 }
console.log('子组件处理逻辑')
}
render () {
return (
<div>当前值:{this.state.count}</div>
)
}
}
const mapStateToProps = state => ({})
// Note: forwardRef parameter is supported in >= v6.0 only
const Module = connect(mapStateToProps, null, null, { withRef: true })(ChildComp)
export default Module
4、在使用redux环境下,父组件(class)调用子组件(hooks)的方法
import React from 'react'
// 父组件
class ParentComp extends React.Component {
constructor(props) {
super(props)
this.buttonRef = React.createRef()
}
handleChange = () => {
this.buttonRef.current.onChangeCount()) // '子组件处理逻辑'
}
render() {
return (
<div>
<button onClick={this.handleChange}>改变子组件的属性</button>
<ChildComp ref={this.buttonRef}/>
</div>
)
}
}
import React, { useState, useImperativeHandle } from 'react'
// 子组件
const ChildComp = (props) => {
const { innerRef } = props
const [count, setCount] = useState(0)
useImperativeHandle(innerRef, () => ({
// 暴露给父组件的属性/方法
count,
onChangeCount,
}))
const onChangeCount = () => {
// ... other logic
setCount(prevCount => prevCount + 1)
console.log('子组件处理逻辑')
}
return (
<div>当前值:{count}</div>
)
};
const mapStateToProps = state => ({})
// Note: This parameter is supported in >= v6.0 only
const Module = connect(mapStateToProps, null, null, { forwardRef: true })(ChildComp)
export default React.forwardRef((props, ref) => <Module {...props} innerRef={ref} />)