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