今天來聊聊前端,其實這個專題剛開始寫起來的時候,是想和大家分享數(shù)據(jù)可視化的一些知識的。這也是圖表君名頭的由來,后來慢慢就寫進(jìn)了些前端的東西,再后來,因為圖表君工作的轉(zhuǎn)換,現(xiàn)在更多的做一些后臺的工作,那么討論的問題就更雜了,現(xiàn)在看起來算是我的一些工作和學(xué)習(xí)心得和感受吧。
好了,說了這么多。今天聊點什么呢?聊聊React。其實這也并不是什么新東西了。2014年,圖表君就知道有這么個東西,聽著幾位業(yè)界大牛聊,說這東西有多么多么的好,當(dāng)時也不是特別的理解,跟了一遍官方的Tutorial,也沒有特別的感受。應(yīng)該是因為當(dāng)時前端的經(jīng)驗特別的淺(雖然現(xiàn)在也不敢說深,捂臉),沒有什么特別的感受吧。
Angular的痛
后來做了幾個項目,使用的是Angular,剛開始覺得雙向數(shù)據(jù)綁定好牛逼啊,好好用,好好用。但是隨著項目逐漸的一點點變大,感覺$scope上的東西是越來越多,各個controller里各有各的$scope,再加上$scope是繼承的,當(dāng)項目一復(fù)雜就越來越難以管理和控制。還有自己要封裝一個組件在angular里得用directive吧,好吧看看directive的文檔你就得暈了,link,compile,controller都是什么鬼。好了,今天不是吐槽angular的時間,但是angular得設(shè)計和使用的確是太復(fù)雜了。
前端到底是在干什么
好了,讓我們先暫時跳出框架的討論,來思考一下,前端的工作到底是干什么的?其實可以簡單的說就是將數(shù)據(jù)到View的一個映射上,也就是說無論什么框架解決的基本問題就是講數(shù)據(jù)展示到View上, 然后將講用戶的操作最后再反應(yīng)到數(shù)據(jù)的變化上來。
Data --> Whatever FrameWork --> View
Data <-- Whatever FrameWork <-- View
再想清楚這個問題之后,React是怎么做的呢?React并不是一個完整的前端框架,只是一個專注于渲染View的library,在看了React的文檔之后,我們會發(fā)現(xiàn)他的api是很簡單的。一個典型的react的組件
class ShoppingList extends React.Component {
render() {
return (
<div className="shopping-list">
<h1>Shopping List for {this.props.name}</h1>
<ul>
<li>Instagram</li>
<li>WhatsApp</li>
<li>Oculus</li>
</ul>
</div>
);
}
}
// Example usage: <ShoppingList name="Mark" />
即使你沒有React的經(jīng)驗,看這樣的代碼也不會有什么特別的問題。好了,今天圖表君不打算安利React,并不想寫一個hello world出來。這樣的文章太多,看看React的官方例子會比圖表君寫的好很多。那么今天說什么呢?
React Thinking - 狀態(tài)機
看這部分之前,圖表君強烈建議你可以看一看React的官方tutorialtutorial,很好的一個例子,也不長。一個小時就能看完,自己上手寫一寫,感受會更深。好了現(xiàn)在假設(shè)你看完了這個tutorial有什么感覺?
圖表君的最大的感受是,最后將State,function都定義到了Game的這個Root級別的Component上了,再把所有的數(shù)據(jù)和function都傳進(jìn)自己的子Component里,需要的地方直接調(diào)用就好了。這樣就使得我們上邊說把Data的操作邏輯都被提出來,并集中在一起了,一下就清晰了,明確了。App管理從此變得一下簡單了。反復(fù)品味這樣的設(shè)計,忽然有個東西,進(jìn)入了我的思維里。這東西不就是一個有限狀態(tài)機呀。
有限狀態(tài)機

有限狀態(tài)機是個十分有用的模型,可以用來模擬世界上大部分的事物,其有三個特征:
- 狀態(tài)總數(shù)(state)是有限的。
- 任一時刻,只處在一種狀態(tài)之中。
- 某種條件下,會從一種狀態(tài)轉(zhuǎn)變(transition)到另一種狀態(tài)。
我們再來看看例子中的代碼
class Game extends React.Component {
constructor(){
super();
this.state={
history:[{
squares: Array(9).fill(null)
}],
stepNumber: 0,
xIsNext: true
}
}
handleClick(i){
const history = this.state.history;
const stepNumber = this.state.stepNumber
const current = history[history.length - 1];
const squares = current.squares.slice();
if (calculateWinner(squares) || squares[i]) {
return;
}
squares[i] = this.state.xIsNext? 'X':'O';
this.setState(
{
history: history.concat([{
squares: squares
}]),
stepNumber: stepNumber + 1,
xIsNext: !this.state.xIsNext,
}
)
}
jumpTo(step){
const newHistory = this.state.history.slice(0,step+1)
console.log(newHistory);
this.setState({
history: newHistory,
stepNumber:step,
xIsNext: (step % 2) ? false: true,
})
}
render() {
const history = this.state.history;
const current = history[this.state.stepNumber];
const winner = calculateWinner(current.squares);
let status;
if(winner){
status = 'Winner Is :' + winner;
}else{
status = 'Next player: ' + (this.state.xIsNext ? 'X':'O');
}
const moves = history.map((step,move) => {
const desc = move ? 'Move #' + move : 'Game Start';
return(
<li key={move}>
<a href="#" onClick={() => this.jumpTo(move)}>{desc}</a>
</li>
)
});
return (
<div className="game">
<div className="game-board">
<Board squares={current.squares} onClick={(i) => this.handleClick(i)} />
</div>
<div className="game-info">
<div>{status}</div>
<ol>{moves}</ol>
</div>
</div>
);
}
}
構(gòu)造方法,constructor - 定義了APP的初始狀態(tài)。
handleClick - 定義了在棋盤里點擊事件后的APP狀態(tài)的變化。
jumpTo - 定義點擊歷史記錄中某一步后APP的狀態(tài)變化。
render- 描述如何在View上來展示當(dāng)前的狀態(tài)。
這樣精巧的設(shè)計,facebook果然聚集了當(dāng)今世界一流的工程師。然后我看了阮一峰的這篇介紹有限狀態(tài)機的文章,看到這段代碼。
var menu = {
// 當(dāng)前狀態(tài)
currentState: 'hide',
// 綁定事件
initialize: function() {
var self = this;
self.on("hover", self.transition);
},
// 狀態(tài)轉(zhuǎn)換
transition: function(event){
switch(this.currentState) {
case "hide":
this.currentState = 'show';
doSomething();
break;
case "show":
this.currentState = 'hide';
doSomething();
break;
default:
console.log('Invalid State!');
break;
}
}
};
有沒有似曾相識的感覺,Redux里是不是就是這么干的?然后再想想Redux,到底干了一件什么事?幫我們做了這樣的一個狀態(tài)機啊,我們開發(fā)者只要定義Action,Reducer,他把我們的APP組織成了一個狀態(tài)機。
從這樣的角度再來看React,Redux這個的技術(shù)棧,我覺得理解的更加的清楚了,當(dāng)然這僅僅是我的一點點小小的思考,歡迎大家一起討論拍磚,后邊逐步的和大家分享我的心得體會。