元件高階知識(受控元件,無狀態元件,高階元件,純元件)
元件高階知識
受控元件(controlled components)
在原生的表單中,input的值是這麼設定的。
<input value="mapbar_front" />
並且在這種情況下,我們能夠給input中輸入任何的值。 但是在react中,我們對於input如果給定一個初始值,它是不會隨便進行輸入進行改變的,它必須同時繫結一個onChange事件。
<input type="text" value={this.state.value} onChange={(e) => this.setState({value: e.target.value})}>
在原生的表單中,textarea標籤的值是由其子元素決定的。例如:
<textarea value="mapbar_front" ></textarea>這個值是空的
<textarea>mapbar_front</textarea>這個值是有的mapbar_front
但是在react中,是由value屬性決定的。 同樣的,這個value屬性的改變,也需要使用onChange時間來進行更改value的狀態。
<textarea value="mapbar_front" ></textarea>
在react中,上面的value值是存在的,不過你不能改變文字框的值,你必須加上一個onChange事件來進行更改。
受控元件的意義,就是在react中,把input,textarea這一類的表單元素,使用onChange事件以及value屬性,動態跟蹤他們的值的改變。
無狀態元件
無狀態元件的意義,在於其良好的效能,它是用一個函式的方式進行表示一個元件的。
import React, { Component } from 'react';
export default function Hello(props) {
return (
<div>hello, {props.name}</div>
);
}
無狀態元件,之所以由比較高的效能,是因為它自身少了一個元件的例項化的一個過程,它本身就是一個函式。
它自身的一切只與props相關,一切需要定義state的地方,你都應該抽離到容器元件上面,或者使用redux之類的東西,進行抽離。
它自身沒有this的概念,因為本身就是一個函式,而class型別的元件是要進行例項化的,所以會有this的概念。
在無狀態元件中,不能使用周期函式,這就要讓我們思考我們的資料結構,怎麼樣才算是顯得更加的高階。
無狀態元件,專注於UI層,它自身不會對業務邏輯進行處理,這就讓我們更好的理解component和page的關係問題。有助於我們進行元件分離。
高階元件
高階元件的本質,是一個函式,只不過這個函式的返回值,是一個class型別的元件。一個高階元件的基本示例如下:
function highComponent(MyComponent) {
return class A extends Component {
constructor(props) {
super(props);
this.state = {
isShow: true
}
}
componentDidMount() {
this.setState({
isShow: false,
})
}
render() {
return (
<MyComponent isShow={this.state.isShow}></MyComponent>
)
}
}
}
從上面的示例中可以看到,高階元件聚焦於業務層,不關心元件的UI層,所以在上面的示例中,我們可以把MyComponent這個傳遞進來的元件,寫成無狀態元件。
pureComponent 和 Component區別
首先,pureComponent是和shouldComponentUpdate這個周期函式相關,正常情況下,這個周期函式預設返回的是true,也就是任何props的改變,或者是任何的setState,都會導致介面的重新render。
pureComponent會改變shouldComponentUpdate的行為,它不再是返回一個true,它會對props和state進行一次淺比較,只有在不相等的情況下,再進行return 一個true,進行觸發render操作。
這個時候,如果是陣列型別,或者Object型別的資料發生變化,對於pureComponent而言,其實都是一樣的,不會觸發render。例如:
import React, { pureComponent } from 'react'
export default class A extends pureComponent{
constructor(props) {
super(props);
this.state = {
name: {
value: 'mapbar'
}
}
this.click = this.click.bind(this);
}
click() {
this.state.name.value = 'mapbar_front';
this.setState({
name: this.state.name
})
}
render() {
return (
<div onClick={this.click}>{this.state.name}</div>
)
}
}
以上的例子,不會觸發render,導致name的值一直是mapbar。