react整理(一) react元件
說起react是一個很寬泛的東西,作為一個從零開始學習react的小白,到現在懂一點react,決心將自己學的東西一一整理,從簡單的開始著手,一是為了鞏固知識,二也是為正在學習的同學提供一些思路,三也是希望大佬能夠指出我的不妥之處,或加以補充,以更深層次的掌握react。
那麼,在學習react之前,我們應該掌握哪些知識?
1.需要熟悉javascript
2.需要使用es6,箭頭函式, 類, 模板字串, let, 和 const 宣告
react是什麼?概括為兩點:
1.用來構建UI的JS庫。
2.React 不是一個MVC框架,僅僅是檢視層(V)層的庫。
react包括哪些概念?
1.元件
2.JSX
3.Virtual DOM
4.Data Flow
第一部分
那麼接下來我們就從構建一個簡單的元件開始。
在之前,我們的js,css,html都是分離的,這種方式滿足不了我們要去實現程式碼複用。元件化,很多前框的框架都開始注重了這一點。一個元件就是一個功能模組,react框架相對來說,實現的更加徹底一些。react各個元件維護自己的狀態和UI,當狀態更變時,自動重新渲染整個元件。
構建react元件,可以是一個類,可以是一個函式。類與函式有什麼區別?
1.類是有狀態的元件,而函式是無狀態的元件。
2.通過類構建一個元件,允許有內部狀態存在,有完整的生命週期。可以使一個元件有生命力並且便於管理。
3.通過類構建必須要繼承react內建的元件類,生命週期都是繼承自react內建的元件類。
4.從效能來說,類構建要稍微慢一些。
如果是不使用生命週期是不是就可以不繼承內建的元件類呢?
答案是不能,如果是使用了class來構建react的元件,必須要繼承react的內建元件,因為class類中必須有一個render()方法來返回元件的例項。不寫render方法它就不可能返回UI,那也就不是一個元件。render方法就是生命週期之一。
首先,我們來建立一個基於class的react元件。
類構建react元件有兩種方式:
1.ES5: React.createClass
2.ES6:React.Component
React.createClass是React剛開始推薦的方式,是與ES5中原生JS來建立react元件方式。React.createClass建立一個類,接受一個物件為引數,並且需要有一個render方法來返回元件例項UI。這種方式我沒有怎麼使用過,不過基本的使用方式如下:
import React from 'react'
import ReactDom from 'react-dom'
const reactDom = React.createClass({
getDefaultProp: function () {
return { open: false }
},
getInitialState: function (){
return { open: this.props.open}
},
handleClick: function(event){
this.setState({
open: !this.state.open
})
},
render: function () {
var open = this.state.open
className = open ? 'switch-button' : 'btn-switch'
return (
<label className={className} onClick={this.handleClick.bind(this)}>
<Input type="checkbox" checked={open} />
</label>
)
}
})
ReactDOM.render(
<reactDom />,
document.getElementById('root')
)
ReactDom是React的最基本方法用於將模板轉為HTML語言,並插入指定的DOM節點。
雖然沒有使用過,但是它的弊端就是:
1.會自動繫結函式方法,造成不必要的效能開銷
2.mixins不夠直觀,自然。(這一點在es6中已經沒有使用了,它主要的作用就是,不同的元件之間,會使用到相同的功能,如果一個元件使用了多個 mixins,其中幾個 mixins 定義了相同的“生命週期方法”,這些方法會在元件相應的方法執行完之後按 mixins 指定的陣列順序執行),可參考http://wiki.jikexueyuan.com/project/react-tutorial/mixin.html
接下來要說的就是目前正使用的方法,使用es6方式來構建react元件。按照上面的方法,應該寫成以下方式。
export default class reactDom extends Component {
constructor(props){
super(props);
this.state = {
open: false
}
}
getDefaultProp() {
return { open: false }
}
getInitialState(){
return { open: this.props.open}
}
handleClick (e){
this.setState({
open: !this.state.open
})
}
render(){
return (
<label className={className} onClick={this.handleClick.bind(this)}>
<Input type="checkbox" checked={open} />
</label>
)
}
}
那麼es5與es6在寫法上有什麼更具體的區別呢?
1.寫法上的不同
React.creatClass 新建立的Class賦給一個常量,再添上render方法來構建出一個基本的元件
es5的寫法:
const Contacts = React.createClass({
render() {
return (
<div></div>
)
}
})
export default Contacts;
es6的寫法:
export default class Contacts extends React.Component({
construct(props){
super(this)
this.state = {}
}
render(){
return(
<div></div>
)
}
})
es6的不同,我們使用super這個函式,來為React.component傳遞屬性,所以需要引用construct()這個方法。es6的寫法更加具有類的意義。
2.propType 和 getDefaultProps
他們的區別在於如何使用、宣告預設屬性和型別,以及如何設定類初始化狀態。propType的作用是,當父元件給子元件傳參時,定義父元件給子元件傳值的型別;getDefaultProps/DefaultProps的任務是父元件給子元件傳參沒有給定預設值時,可以在getDefaultProps/DefaultProps中定義。
es5寫法:
const Contacts = React.createClass({
propType: {},
getDefaultProps: (){
return {
}
}
render() {
return (
<div></div>
)
}
})
export default Contacts
在呼叫 React.createClass,定義propTypes 的物件,只要給它的屬性進行賦值就能宣告對應屬性的型別。 getDefaultProps 這個函式返回了一個物件,這個物件的所有屬性將會作為元件的初始化屬性
使用es6的寫法,個人更喜歡這樣的寫法,他更簡潔直觀了:
export default Contacts extends React.Component {
// static 不繼承例項,直接通過類來呼叫的靜態方法
static propType = {
},
static defaultProps = {
}
render() {
return (
<div></div>
)
}
}
3.state的不同
外部資料來源我們用props來儲存資料,而state是用來管理內部資料狀態的。使用es5,state是放在getInitialState()方法中,返回一個包含元件初始化狀態的物件。
es5寫法具體如下:
const Contact = React.CreateClass{
getInitialState () {
return {
}
}
render(){
return (
<div></div>
)
}
}
export default Contact;
在es6中,廢除了getInitialState()這個方法,狀態的定義在construct建構函式裡。例如這樣:
export default Contact extends React.Component {
construct (props) {
super(props);
this.state = {}
}
render(){
return (
<div></div>
)
}
}
4.this的使用不同
es5中會自動繫結this,比如說
const Contact = React.createClass({
handleClick () {
console.log(this)
},
render(){
return (
<div onClick={this.handleClick}></div>
)
}
})
export default Contact;
這裡的this可以自動的找到當前執行環境的上下文,不用我們操心,但是這樣我們語法結構時,可能要去改變jsx部分(支援js,css,html混合在一起的寫法)結構。
如果使用的是es6的語法,this不會自動去繫結上下文,而是需要自己繫結正確的上下文,就像下面的例子一樣。
export default class Contact extends React.Component {
handleClick () {
console.log(this)
}
render () {
return (
<div onClick={this.handleClick.bind(this)}></div>
)
}
}
5.mixins
es5中還儲存有mixins這個特性,而es6中已廢棄了這個特性,取而代之的是高階元件,不過這一塊還不瞭解,會繼續學習。
接下來,我們建立一個無狀態元件
無狀態的元件我們通常是做純UI展示。不需要去定義元件狀態不用考慮元件的生命週期,就像這樣:
class MessageView extends React.Component {
render({
return(
<div className="container">
<div className="from">
<span className="label">From: </span>
<span className="value">JohnDoe</span>
</div>
<div className="message">
<span className="label">Message: </span>
<span className="value">Have a great day!</span>
</div>
</div>
) } }
export default MessageView;
因為是純UI展示,所以也可以不考慮生命週期,不繼承Component,於是可改寫成:
export default function MessageView({message}) {
return(
<div className="container">
<div className="from">
<span className="label">From: </span>
<span className="value">{message.from}</span>
</div>
<div className="message">
<span className="label">Message: </span>
<span className="value">{message.content}</span>
</div>
</div>
) }}
那麼無狀態與有狀態元件,我們怎麼用呢?
如果要考慮生命週期,那麼就用使用類構建react例項,如果不考慮生命週期,那麼使用無狀態函式式構建。
一般來說,ES6的寫法是優於ES5寫法的。
以上是我的總結,如有疑問可留言。
參考資料:
https://www.w3cplus.com/react/stateful-vs-stateless-components.html © w3cplus.com