早在一年前掂墓,我就很蠢發(fā)表過一篇關(guān)于React的文章,這篇文章主要根據(jù)React官方的介紹初步介紹一下React夸研,并稍微帶過一下Webpack永部,當(dāng)時只是作為一位iOS開發(fā)工程師隨便看看React這個東西,現(xiàn)在博主已經(jīng)勵志從一名懂一點Javascript的iOS程序員轉(zhuǎn)變成一位曾經(jīng)做過iOS的前端開發(fā)人員,在自己做過一些React項目之后信不,想再次介紹一下React這個東西
那么讓我們來回顧一下React的基本用法嘲叔,在某個版本之后React這個庫被分為react和react-dom,react負責(zé)對組件的操作抽活,react-dom負責(zé)將組件渲染到頁面上硫戈,組件的寫法基本為:
var MyComponent = React.createClass({
render: function() {
return React.createElement("div", null);
}
})
使用JSX語法之后
var MyComponent = React.createClass({
render: function() {
return (
<div>
<!-- add some dom code -->
</div>
)
}
})
使用ES6的語法來寫:
class MyComponent extends React.Component {
render() {
return (
<div>
<!-- add some dom code -->
</div>
)
}
}
在Babel橫行的當(dāng)今,我是推薦至少要使用JSX的語法來編寫React的下硕,這樣會使得代碼的可讀性更強丁逝,至于ES6就靠個人洗好了,本文還是推薦使用ES6的語法的梭姓,也將使用ES6語法完成大部分代碼的示例
隨便說說生命周期
關(guān)于組件的裝載霜幼,按照順序執(zhí)行下面的方法
constructor
,componentWillMount
誉尖,render
罪既,componentDidMount
關(guān)于組件的更新,按照順序執(zhí)行下面的方法
componentWillReceiveProps
铡恕,shouldComponentUpdate
琢感,componentWillUpdate
,render
探熔,componentDidUpdate
關(guān)于組件卸載的
componentWillUnmount
英語好的看名字就知道是干嘛的了驹针,真的,應(yīng)該不用解釋了
這里稍微提及一下就是在使用ES6的時候诀艰,定義class如下代碼:
class A extends React.Component {
custom() {
}
render() {
console.log(this.custom)
return (
<div>
<A customProp="custom"/>
</div>
)
}
}
此處輸出this.custom
的時候會顯示undefined
柬甥,因為class的非constructor方法都是prototype,可以在this._proto_
中訪問到其垄,如果想要比較友好的使用this.custom
暗甥,可以使用auto-bind
React組件核心的兩個屬性分別叫做props和state,這兩個屬性其實就是存儲了一系列數(shù)據(jù)捉捅,props的數(shù)據(jù)主要從組件外部傳入,比如
class A extends React.Component {
render() {
const {customProp} = this.props
console.log(customProp)
return (
<div></div>
)
}
}
class B extends React.Component {
render() {
return (
<div>
<A customProp="custom"/>
</div>
)
}
}
以上就會輸出customProp的值為custom
而state的值則是由組件內(nèi)部控制的虽风,state應(yīng)當(dāng)在constructor
的實現(xiàn)中初始化棒口,并在React中調(diào)用setState()
組件會做diff并刷新相應(yīng)界面,所以我們能夠確定props對于組件內(nèi)部是靜態(tài)的辜膝,它從外部傳入无牵,由外部控制組件。而state是動態(tài)的厂抖,組件自己控制自己茎毁。
了解了以上的知識,基本的React項目已經(jīng)可以編寫了,當(dāng)然七蜘,只要配置好Webpack谭溉,關(guān)于項目的搭建,之前已經(jīng)有過一篇文章對其進行過翻譯
那么接下來講講一些進階吧
Redux
首先呢橡卤,Redux不是只用于React的扮念。當(dāng)然了React和它很搭,React是一個狀態(tài)維護組件的界面框架碧库,而Redux恰好是一個非常好的能夠維護狀態(tài)的框架柜与。接下來對Redux做一些介紹,Redux只適用于超大型項目嵌灰,輕易別用這個東西弄匕,很累贅。
那么我們從基礎(chǔ)的來看Redux
Action
Action相當(dāng)于指令沽瞭,一般會包含兩種屬性一種是指令類型迁匠,用以區(qū)分指令,另一種是數(shù)據(jù)秕脓,數(shù)據(jù)可以有很多柒瓣,用來處理,當(dāng)然也可以沒有數(shù)據(jù)單純發(fā)一個指令吠架,這都是可選的芙贫,比如以下都是Action:
const OPEN_MOUTH = "OPEN_MOUTH"
const CLOSE_MOUTH = "CLOSE_MOUTH"
const openAction = {
type: OPEN_MOUTH,
size: 10,
time: 5
}
const closeAction = {
type: CLOSE_MOUTH
}
上面一共有兩個Action,OPEN_MOUTH
傍药、CLOSE_MOUTH
分別是兩個類型磺平,openAction
中的size和time是數(shù)據(jù),closeAction
中沒有數(shù)據(jù)
Reducer
Reducer是指令的處理器拐辽,用于分類處理指令拣挪,先上一段代碼:
function myReducer(state, action) {
if (action.type == OPEN_MOUTH) {
var newState
//create a new State for open mouth
return newState
} else if (action.type == CLOSE_MOUTH) {
var newState
//create a new State for close mouth
return newState
}
}
這就是一個Reducer,可以看到俱诸,這個Reducer接受兩個參數(shù)菠劝,一個是原來的state,一個是action睁搭,也就是我們的指令赶诊,通過指令的類型和指令的數(shù)據(jù)來產(chǎn)生新的state就是Reducer的任務(wù)。
這里需要注意园骆,Redux開發(fā)過程中舔痪,在Reducer處理的時候都是期望state純凈的,也就是說锌唾,產(chǎn)生的新的state不會修改老的state锄码,所以請巧用Object.assign()
,concat()
等函數(shù)經(jīng)行操作
Store
可以通過createStore
來創(chuàng)建新的store對象,store對象主要的功能是發(fā)送Action滋捶,和監(jiān)控整個發(fā)送處理過程
let store = createStore(myReducer, {})
store.dispatch(openAction)
createStore
第一個參數(shù)為Reducer痛悯,第二個參數(shù)是初始的state值
dispatch
方法發(fā)送Action
以上就是最簡單的Redux的用法,想了想其實就是很簡單的東西炬太,如果要我們自己來實現(xiàn)的話我們也可以來演示一遍灸蟆,主要就是實現(xiàn)一個store
var createStore = (reducer, init) => {
var store = {}
var state = init
var listeners = []
store.dispatch = (action) => {
state = reducer(state, action)
listeners.forEach((listener) => {
listener()
})
}
store.getState = () => {
return state
}
store.subscribe = (listener) => {
let count = listeners.push(listener)
return () => {
listeners.slice(count - 1, 1)
}
}
return store
}
以上就是createStore的大致實現(xiàn),很簡單對不對亲族,所以如果只是想用這個Redux的功能炒考,完全可以用這么點代碼代替,不用使用一整個Redux的庫霎迫,殺雞焉用牛刀
那么我們來繼續(xù)介紹一些斋枢,Redux還有哪些Api
combineReducers
隨著項目越來越復(fù)雜,一個Reducer處理的數(shù)據(jù)就會越來越多知给,比如針對如下的數(shù)據(jù):
{
user: {
name: 'goodname',
sex: 1
},
setting: {
showing: false,
count: 100
}
}
當(dāng)我們修改user的時候其實setting根本沒有被修改瓤帚,隨著同級的屬性的增多,把所有的屬性的操作都放入一個reducer涩赢,代碼難免會有一些雜亂戈次,那么我們就會把Reducer拆分,讓單個Reducer來處理單個同級屬性筒扒,combineReducers
就幫我們很好的處理了這件事情怯邪。比如針對上面的數(shù)據(jù),我們之前會這么做
var reducer = (state, action) => {
if (action.type == CHANGE_NAME) {
} else if (action.type == CHANGE_SEX) {
} else if (action.type == SHOWING) {
} else if (action.type == HIDE) {
}
}
同級屬性再增多花墩,都會把所有的操作都放在這個函數(shù)中悬秉,是不好的,有了combineReducers
冰蘑,我們可以這么做:
var user = (state, action) => {
if (action.type == CHANGE_NAME) {
} else if (action.type == CHANGE_SEX) {
}
}
var setting = (state, action) => {
if (action.type == SHOWING) {
} else if (action.type == HIDE) {
}
}
module.exports = combineReducers({user, setting})
這么做就會自動分發(fā)屬性名對應(yīng)的Reducer來處理了(當(dāng)然對應(yīng)關(guān)系可以自己設(shè)置)
////未完待續(xù) -> redux-react