咱們建立一個定時器來維護state中的date,模擬每秒時間變化,同時放置一個輸入框。這樣狀態是一直更新的,輸入框是固定的DOM元素,咱們在輸入框輸入內容,若是狀態更新時間變化,而輸入框內的內容沒有重置爲空,說明有算法參與,識別input節點沒有變化,則沒有觸發更新。react
class Time extends React.Component{
state={
date:new Date()
}
componentDidMount(){
setInterval(()=>{
this.setState({date : new Date()})
},1000)
}
render(){
return(
<div> <h1>Hello</h1> <input type="text" /> <h2>如今是北京時間:{this.state.date.toTimeString()} <input type="text" /> </h2> 時間每隔一秒刷新一次 而h1和input標籤不變化不從新渲染 因此在頁面input中輸入內容不被清空 </div>
)
}、
}
ReactDOM.render(<Time/>,document.getElementById('test'))
複製代碼
結果很容易預測,input框內容確實不會被清空。
而代碼中跟時間處於同一標籤內的 ‘如今是北京時間:’也會跟着狀態變化而更新
但h2標籤中嵌套的input輸入內容,依然不會更新
因此Diffing算法會逐層對比,最小粒度是標籤(節點)算法
舉個栗子:數組
class Person extends React.Component{
state={
people:[
{id:'1',name:'老秦',age:'22'},
{id:'2',name:'小唐',age:'38'},
{id:'3',name:'阿香',age:'27'},
]
}
componentDidMount(){
setInterval(()=>{
this.setState({date : new Date()})
},1000)
}
add = () =>{
const { people } = this.state
const p = { id:people.length+1,name:'坤泰',age:39}
this.setState({people:[p , ...people]})
}
render(){
return(
<div> <h2>展現人員信息</h2> <button onClick={this.add}>添加人員</button> <span>索引值做爲key</span> <ul> { this.state.people.map((item,index)=>{ return( <li key={index}>{item.name}----{item.age}<input type="text"/></li> ) }) } </ul> <span>惟一標識做爲key</span> <ul> { this.state.people.map((item)=>{ return( <li key={item.id}>{item.name}----{item.age}<input type="text"/></li> ) }) } </ul> </div>
)
}
}
ReactDOM.render(<Person/>,document.getElementById('test'))
複製代碼
代碼中對一組數據分別以索引值index做爲key和惟一標識id做爲key遍歷生成具體DOM元素。
點擊按鈕在原數組前插入一條新的人員信息時,
索引值做爲key:
建立虛擬DOM時,新插入的數據索引值index爲0,原來的數據索引值依次加1,以此來建立虛擬DOM。 注意注意了兄弟萌,這時候Diffing算法過來跟這幾條數聽說把大家的key拿出來吧我瞅瞅,一看好傢伙虛擬DOM的key跟原來真實DOM的key沒一個同樣的,你琢磨琢磨key都不同了,是不得把這些數據全得從新渲染成真實DOM。原本只要渲染新插入的一條,就由於你的蹩腳行爲,致使如今三條都要從新渲染。
若是在你渲染數據時,順手依據索引值渲染一個輸入框輸入各自對應的姓氏,index一旦變了全改姓了車禍現場
惟一標識做爲key:
這就不用說了,key爲惟一值不會變化很是穩健,渲染時比對直接渲染新增的key對應的DOM元素便可。markdown
總結:ui
1.虛擬DOM中key的做用:
1).簡單的說: key是虛擬DOM對象的標識,在更新顯示時key起着極其重要的做用 2).詳細的說:當狀態中的數據發生變化時,react會根據【新數據】生成新的虛擬DOM 隨後React進行了【新虛擬DOM】和【舊虛擬DOM】的比較,比較規則以下: a:舊虛擬DOM找到了與新虛擬DOM相同的key: (1).若虛擬DOM中內容沒變,直接使用以前的真實DOM (2).若虛擬DOM中內容變了,則生成新的真實DOM,隨後替換頁面中以前的真實DOM b:舊虛擬DOM中未找到與新虛擬DOM相同的key 根據數據建立新的真實DOM隨後渲染到頁面
2.用index做爲key可能會引起的問題:
1).若對數據進行:逆序添加、逆序刪除等破壞順序的操做: 會產生沒有必要的真實DOM更新 ===>界面效果沒問題 但效率低
2).若是結構中還包含輸入類的DOM 會產生錯誤的DOM更新 ===>界面有問題
3).注意:若是不存在對數據的逆序添加 逆序刪除等破壞順序的操做,僅用於渲染列表展現, 使用index做爲key是沒有問題的。
3.開發中如何選擇key
1).最好每條數據的惟一標識做爲key,好比id 2).若是隻是簡單的展現數據,index也能夠 複製代碼