【前言】
前兩篇講到props、state,可是阿,有時候看到滿滿jquery的特效就很想拿來react用,可是jquery那些都要直接對實體DOM做操作;抑或是想對input欄位抓取value、使用focus()這些方法,但react本身就是virtual DOM,是要怎樣讓他們抓到啦?難不成只能忍痛放棄炫砲的網頁嗎......
【正文】
為了解決上面這個問題,react提出一種Refs
概念,使用這個方法,我們就可以抓取到react裡面的DOM元素,那有什麼樣的時機可以嘗試用用看Refs
呢?
- Managing focus, text selection, or media playback. // 想要使用input的foucs(),video的play()
- Triggering imperative animations. // 要觸發一些動畫
- Integrating with third-party DOM libraries. // 集結第三方DOM Library,如jquery
當然有些人想說,有了ref之後,我基本上就可以把react component DOM內的元素當成實體DOM,那也就是我可以任意用囉,理論和實作上也不是不行,只是這樣就失去react當初設計的用意了,如果當你在實作一個功能的時候,如果可以利用props及state就可以達到的方法的話,那就盡量用props和state完成,即是「非必要情況,盡量避免用refs」。
那在今天的練習會利用refs去做些簡單的代辦清單,程式碼如下:
import React from 'react';
class App extends React.Component {
constructor(props) { // 在建構函式設定state的初始值
super(props);
this.state = {
itemList: [],
};
this.addFiled = React.createRef(); // 在建構函式創建refs屬性
}
addItem = () => { // 利用arrow function additem function
const { itemList } = this.state;
// 利用ES6 Object.assign()拷貝itemList
const tempList = Object.assign([], itemList);
// 抓取inputDOM元素的value值,在ref的current屬性
if (this.addFiled.current.value !== '') {
// array.push新值,這會回傳一個陣列長度
tempList.push(this.addFiled.current.value);
// 利用setState更新state的值
this.setState({
itemList: tempList,
});
// 把input的value變回空字串
this.addFiled.current.value = '';
}
}
render() {
const { itemList } = this.state;
return (
<div style={{ textAlign: 'center', width: '300px' }}>
{/* 在你想要參考的地方增加ref屬性 */}
<input type="text" name="addField" ref={this.addFiled} />
<button type="button" onClick={this.addItem}>ADD</button>
<ul style={{ textAlign: 'left' }}>
{ itemList.map((item, index) => <li key={`item_${index}`}>{item}</li>) }
</ul>
</div>
);
}
}
export default App;
實作效果如下:
這樣有沒有稍稍了解了refs了呢?明天我們來說說Component的lifeCycle吧!