1. 程式人生 > >React從入門到精通系列之(14)refs和DOM元素

React從入門到精通系列之(14)refs和DOM元素

https://segmentfault.com/u/zhangyatao/articles在典型的React資料流中,props是父元件與其子元件互動的唯一方式。 要修改子元件,需要使用一個新的props進行重新渲染。

但是,在某些情況下,您需要在典型資料流之外強制修改子元件。 要修改的子元件可以是React元件例項,也可以是DOM元素。 對於這兩種情況,React提供了一個以下這樣的功能。

通過ref屬性設定回撥函式

React提供可以附加到任何元件的特殊屬性。 ref屬性接受一個回撥函式,回撥函式將在元件被掛載或解除安裝後立即執行。

當在HTML元素上使用ref屬性時,ref回撥函式接收一個基礎的DOM元素作為其引數。 例如,此程式碼使用ref

回撥函式來儲存對DOM節點的引用:

import React from 'react';
import ReactDOM from 'react-dom';

class CustomTextInput extends React.Component {
    constructor(props) {
        super(props);
        this.focus = this.focus.bind(this);
    }

    focus() {
        // textInput是一個標準的DOM元素
        this.textInput.focus();
    }

    render() {
        return
( <div> <input type="text" ref={input => { this.textInput = input; }}/> <input type="button" value="選中上面的text input" onClick={this.focus}/> </div> ); } } ReactDOM.render( <CustomTextInput
/>
, document.getElementById('root') );

當元件裝載(mounting)時,React將使用DOM元素呼叫ref回撥函式,並在解除安裝時用null呼叫它。

使用ref回撥函式是為類設定一個屬性來訪問DOM元素的常見模式。 如果您目前正在使用this.refs.myRefName來訪問DOM引用的話,我會建議你使用此模式。

當在自定義元件上使用ref屬性時,ref回撥接收元件的已裝入的元件例項作為其引數。 例如,如果我們想要包裝上面的CustomTextInput來模擬它在裝載(mounting)後立即被點選:

class AutoFocusTextInput extends React.Component {
    componentDidMount() {
        this.textInput.focus();
    }
    render() {
        return (
            <CustomTextInput ref={input => {this.textInput = input; }} />
        );
    }
}

您不能在功能性元件上使用ref屬性,因為它們沒有例項。 但是,您可以使用功能性元件的render函式內的ref屬性:

function CustomTextInput(props) {
    // 這裡必須提前頂一個textInput,只有這樣才可以正常執行ref回撥函式
    let textInput = null;
    function click() {
        textInput.focus();
    }
    return (
        <div>
            <input type="text" ref={input => { textInput = input; }} />
            <input type="button" value="選中這個輸入框" onClick={this.click} />
        </div>
    );
}

不要過度使用ref

你的第一個傾向可能是使用refs在你的應用中“make things happen”

如果是這種情況,你必須花一點時間,關鍵去考慮在元件層次結構中應該擁有什麼狀態。通常,在層次結構中處於更高級別的元件“擁有”狀態是一個讓一切便清除的最適當位置。 有關示例,請參閱本系列的第10篇《提升state》。