大部分情況下你不需要通過查詢 DOM 元素去更新組件的
UI,你只要關(guān)注設(shè)置組件的狀態(tài)(setState)。但是可能在某些情況下你確實(shí)需要直接操作 DOM。
首先我們要了解 ReactDOM.render 組件返回的是什么?
它會(huì)返回對組件的引用也就是組件實(shí)例(對于無狀態(tài)狀態(tài)組件來說返回 null),注意 JSX
返回的不是組件實(shí)例,它只是一個(gè) ReactElement 對象(還記得我們用純 JS 來構(gòu)建 JSX
的方式嗎),比如這種:
// A ReactElement
const myComponent = <MyComponent />
// render
const myComponentInstance = ReactDOM.render(myComponent, mountNode);
myComponentInstance.doSomething();
當(dāng)組件加載到頁面上之后(mounted),你都可以通過 react-dom 提供的 findDOMNode() 方法拿到組件對應(yīng)的
DOM 元素。
import { findDOMNode } from 'react-dom';
// Inside Component class
componentDidMound() {
const el = findDOMNode(this);
}
findDOMNode() 不能用在無狀態(tài)組件上。
另外一種方式就是通過在要引用的 DOM 元素上面設(shè)置一個(gè) ref
屬性指定一個(gè)名稱,然后通過 this.refs.name 來訪問對應(yīng)的 DOM 元素。
比如有一種情況是必須直接操作 DOM 來實(shí)現(xiàn)的,你希望一個(gè) <input/>
元素在你清空它的值時(shí) focus,你沒法僅僅靠 state 來實(shí)現(xiàn)這個(gè)功能。
class App extends Component {
constructor() {
return { userInput: '' };
}
handleChange(e) {
this.setState({ userInput: e.target.value });
}
clearAndFocusInput() {
this.setState({ userInput: '' }, () => {
this.refs.theInput.focus();
});
}
render() {
return (
<div>
<div onClick={this.clearAndFocusInput.bind(this)}>
Click to Focus and Reset
</div>
<input
ref="theInput"
value={this.state.userInput}
onChange={this.handleChange.bind(this)}
/>
</div>
);
}
}
如果 ref 是設(shè)置在原生 HTML 元素上,它拿到的就是 DOM
元素,如果設(shè)置在自定義組件上,它拿到的就是組件實(shí)例,這時(shí)候就需要通過
findDOMNode 來拿到組件的 DOM 元素。
因?yàn)闊o狀態(tài)組件沒有實(shí)例,所以 ref
不能設(shè)置在無狀態(tài)組件上,一般來說這沒什么問題,因?yàn)闊o狀態(tài)組件沒有實(shí)例方法,不需要
ref 去拿實(shí)例調(diào)用相關(guān)的方法,但是如果想要拿無狀態(tài)組件的 DOM
元素的時(shí)候,就需要用一個(gè)狀態(tài)組件封裝一層,然后通過 ref 和 findDOMNode
去獲取。
this.refs.myTypeahead.reset()render 或者 render 之前訪問 refsrefs,比如只是用它來按照傳統(tǒng)的方式操作界面 UI:找到 DOM -> 更新 DOM