Refs
允許我們訪問真實 DOM
一般的,React 數(shù)據(jù)流是通過 props 來實現(xiàn)父子組件的交互
Refs 允許我們用于強(qiáng)制修改子組件
// 輸入框焦點
class MyInput extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
inputOperating() {
console.log(this.inputRef.current.value);
this.inputRef.current.focus();
}
render() {
return (
<div>
<input type="text" ref={this.inputRef} />
<button onClick={this.inputOperating.bind(this)}>獲取焦點</button>
</div>
);
}
}
// 媒體管理
class MyVideo extends React.Component {
constructor() {
super();
this.vdoRefs = React.createRef();
}
vdoPause() {
this.vdoRefs.current.pause();
}
vdoPlay() {
this.vdoRefs.current.play();
}
render() {
return (
<div>
<video
ref={this.vdoRefs}
src="http://vjs.zencdn.net/v/oceans.mp4"
controls
autoPlay
muted
></video>
<button onClick={this.vdoPause.bind(this)}>暫停</button>
<button onClick={this.vdoPlay.bind(this)}>播放</button>
</div>
);
}
}
// 操作動畫
class MyBox extends React.Component {
constructor(props) {
super(props);
this.boxRef = React.createRef();
}
boxExtend() {
const oBox = this.boxRef.current;
oBox.style.width = "500px";
oBox.style.height = "500px";
}
render() {
return (
<>
<div
ref={this.boxRef}
style={{
width: 200 + "px",
height: 200 + "px",
backgroundColor: "orange",
transition: "all 1s",
}}
></div>
<button onClick={this.boxExtend.bind(this)}>Extend</button>
</>
);
}
}
createRef 用法細(xì)節(jié)
- 通過
createRef創(chuàng)建ref對象 - 通過元素的
ref屬性可以附加到React元素上 - 一般通過構(gòu)造器中給
this賦值一個ref,方便整個組件使用 -
ref只要傳遞React元素中,就可以利用ref的current屬性訪問到該真實DOM節(jié)點 - ref 在
componentDidMount和componentDidUpdate觸發(fā)前更新
ref 不同的使用方式:
-
ref放在HTML元素上,則指向真實DOM節(jié)點 -
ref放在class組件上,則指向組件實例
<MyBox ref={xxx}/> - ref 放在函數(shù)組件上,不能增加
ref屬性,可以使用React.useRef()
forwardRef (v16.3 以上版本)
將子組件的 ref 暴露給父組件
React.forwardRef((props, ref) => { return React 元素})
const MyInput = React.forwardRef((props, ref) => (
// ref 參數(shù)只能在,用 forwardRef 定義的組件內(nèi)可接收
<input type="text" placeholder={props.placeholder} ref={ref} />
));
class App extends React.Component {
constructor(props) {
super(props);
this.myInputRef = React.createRef();
}
inputOperate() {
this.myInputRef.current.value = "";
this.myInputRef.current.focus();
}
render() {
return (
<div>
<MyInput placeholder="請輸入" ref={this.myInputRef} />
<button onClick={this.inputOperate.bind(this)}>獲取焦點</button>
{/* <MyVideo /> */}
{/* <MyBox ref={xxx}/> */}
</div>
);
}
}
// 高階組件 ref 轉(zhuǎn)發(fā)
class MyInput extends React.Component {
render() {
return <input type="text" placeholder={this.props.placeholder} />;
}
}
function InputHoc(WarpperComponent) {
class Input extends React.Component {
render() {
const { forwardRef, ...props } = this.props;
return <WarpperComponent ref={forwardRef} {...props} />;
}
}
function forwardRef(props, ref) {
return <Input forwardRef={ref} {...props} />;
}
// 設(shè)置別名
forwardRef.displayName = `Input - ${WarpperComponent.name}`;
return React.forwardRef(forwardRef);
// return React.forwardRef((props, ref) => (
// <Input forwardRef={ref} {...props} />
// ));
}
const MyInputHoc = InputHoc(MyInput);
class App extends React.Component {
constructor(props) {
super(props);
this.myInputRef = React.createRef();
}
componentDidMount() {
console.log(this.myInputRef);
}
inputOperate() {
this.myInputRef.current.value = "";
this.myInputRef.current.focus();
}
render() {
return (
<>
<MyInputHoc ref={this.myInputRef} placeholder="請輸入" />
<button onClick={this.inputOperate.bind(this)}>獲取焦點</button>
</>
);
}
}
Refs 轉(zhuǎn)發(fā)(v16.2 及以下)
- 通過 props 轉(zhuǎn)發(fā)
class MyInput extends React.Component {
render() {
return <input type="text" ref={this.props.inputRef} />;
}
}
// 通過 props 轉(zhuǎn)發(fā)
class App extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
componentDidMount() {
console.log(this.inputRef);
}
render() {
return (
<div>
<MyInput inputRef={this.inputRef} />
</div>
);
}
}
- 回調(diào) Refs
class App extends React.Component {
constructor(props) {
super(props);
this.inputRef = null;
}
setMyInput(el) {
this.inputRef = el;
}
focusInput() {
this.inputRef.value = "";
this.inputRef.focus();
}
render() {
return (
<div>
<input type="text" ref={this.setMyInput.bind(this)} />
<button onClick={this.focusInput.bind(this)}>click</button>
</div>
);
}
}
- 字符串
refs(不建議使用)
- 組件實例下面的
refs集合里的ref - 需要 React 保持跟蹤當(dāng)前正在渲染的組件,
this沒法確定 - React 獲取
ref可能會比較慢 - 不能在 render 中工作
- 不能組合,只能設(shè)置一個
ref
class App extends React.Component {
componentDidMount() {
// 字符串 refs
console.log(this.refs.inputRef);
}
render() {
console.log(this.refs.inputRef); // undefined
return (
<div>
<input type='text' ref='inputRef' />
</div>
);
}
}