/* * @Description: ref 的场景和 传送门 Portal 作用以及使用 * @Version: 2.0 * @Autor: lhl * @Date: 2020-06-01 10:20:33 * @LastEditors: lhl * @LastEditTime: 2020-06-02 14:07:17 */ import React, { Component, useRef } from 'react' import ReactDOM from 'react-dom' export default class App extends Component { render() { return ( <div>
<p>hello react</p>
<FunRef abc="111"></FunRef>
<RefClassComponent></RefClassComponent>
<CbRef></CbRef>
<Dialog></Dialog>
</div> ) } } // 默认情况下,你不能在函数组件上使用 ref 属性,因为它们没有实例 // 但是特别的,你可以在函数组件内部使用 ref 属性,只要它指向一个 DOM 元素或 class 组件 // 如果要在函数组件中使用 ref,你可以使用 forwardRef 或者可以将该组件转化为 class 组件 function FunRef(props) { console.log(props) // {abc: "111"} // 这里必须声明 textInput,这样 ref 才可以引用它 const textInput = useRef(null); function handleClick() { textInput.current.focus(); } return ( <div>
<input type="text" ref={textInput} />
<input type="button" value="聚焦" onClick={handleClick} />
</div> ); } // class 组件中ref的使用 如果你目前还在使用 this.refs.xx 这种方式访问 refs ,现在建议用回调函数或 createRef API 的方式代替 class RefClassComponent extends Component { constructor(props) { super(props); this.myRef = React.createRef(); } render() { return <div ref={this.myRef} />; } } // 回调函数的方式 访问 refs React.forwardRef 接受一个渲染函数,其接收 props 和 ref 参数并返回一个 React 节点 class CbRef extends Component { render() { return ( <FunRef inputRef={el => this.inputElement = el} /> ); } } // createPortal 传送门的使用 Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案 class Dialog extends React.Component { constructor(props) { super(props); this.el = document.createElement('div'); this.el.setAttribute('class', 'dailog-box'); } componentDidMount() { document.body.appendChild(this.el); } componentWillUnmount() { document.body.removeChild(this.el); } render() { return ReactDOM.createPortal(( <div className="dailog-content"> 弹窗内容 </div> ), this.el); } }