今天來聊聊前端,其實這個專題剛開始寫起來的時候,是想和你們分享數據可視化的一些知識的。這也是圖表君名頭的由來,後來慢慢就寫進了些前端的東西,再後來,由於圖表君工做的轉換,如今更多的作一些後臺的工做,那麼討論的問題就更雜了,如今看起來算是個人一些工做和學習心得和感覺吧。javascript
好了,說了這麼多。今天聊點什麼呢?聊聊React。其實這也並非什麼新東西了。2014年,圖表君就知道有這麼個東西,聽着幾位業界大牛聊,說這東西有多麼多麼的好,當時也不是特別的理解,跟了一遍官方的Tutorial,也沒有特別的感覺。應該是由於當時前端的經驗特別的淺(雖然如今也不敢說深,捂臉),沒有什麼特別的感覺吧。html
後來作了幾個項目,使用的是Angular,剛開始以爲雙向數據綁定好牛逼啊,好好用,好好用。可是隨着項目逐漸的一點點變大,感受$scope上的東西是愈來愈多,各個controller裏各有各的$scope,再加上$scope是繼承的,當項目一複雜就愈來愈難以管理和控制。還有本身要封裝一個組件在angular裏得用directive吧,好吧看看directive的文檔你就得暈了,link,compile,controller都是什麼鬼。好了,今天不是吐槽angular的時間,可是angular得設計和使用的確是太複雜了。前端
好了,讓咱們先暫時跳出框架的討論,來思考一下,前端的工做究竟是幹什麼的?其實能夠簡單的說就是將數據到View的一個映射上,也就是說不管什麼框架解決的基本問題就是講數據展現到View上, 而後將講用戶的操做最後再反應到數據的變化上來。java
Data --> Whatever FrameWork --> View Data <-- Whatever FrameWork <-- View
再想清楚這個問題以後,React是怎麼作的呢?React並非一個完整的前端框架,只是一個專一於渲染View的library,在看了React的文檔以後,咱們會發現他的api是很簡單的。一個典型的react的組件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的經驗,看這樣的代碼也不會有什麼特別的問題。好了,今天圖表君不打算安利React,並不想寫一個hello world出來。這樣的文章太多,看看React的官方例子會比圖表君寫的好不少。那麼今天說什麼呢?git
看這部分以前,圖表君強烈建議你能夠看一看React的官方tutorialtutorial,很好的一個例子,也不長。一個小時就能看完,本身上手寫一寫,感覺會更深。好了如今假設你看完了這個tutorial有什麼感受?github
圖表君的最大的感覺是,最後將State,function都定義到了Game的這個Root級別的Component上了,再把全部的數據和function都傳進本身的子Component裏,須要的地方直接調用就行了。這樣就使得咱們上邊說把Data的操做邏輯都被提出來,並集中在一塊兒了,一下就清晰了,明確了。App管理今後變得一下簡單了。反覆品味這樣的設計,突然有個東西,進入了個人思惟裏。這東西不就是一個有限狀態機呀。api
有限狀態機是個十分有用的模型,能夠用來模擬世界上大部分的事物,其有三個特徵:前端框架
狀態總數(state)是有限的。框架
任一時刻,只處在一種狀態之中。
某種條件下,會從一種狀態轉變(transition)到另外一種狀態。
咱們再來看看例子中的代碼
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> ); } }
構造方法,constructor - 定義了APP的初始狀態。
handleClick - 定義了在棋盤裏點擊事件後的APP狀態的變化。
jumpTo - 定義點擊歷史記錄中某一步後APP的狀態變化。
render- 描述如何在View上來展現當前的狀態。
這樣精巧的設計,facebook果真彙集了當今世界一流的工程師。而後我看了阮一峯的這篇介紹有限狀態機的文章,看到這段代碼。
var menu = { // 當前狀態 currentState: 'hide', // 綁定事件 initialize: function() { var self = this; self.on("hover", self.transition); }, // 狀態轉換 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,到底幹了一件什麼事?幫咱們作了這樣的一個狀態機啊,咱們開發者只要定義Action,Reducer,他把咱們的APP組織成了一個狀態機。
從這樣的角度再來看React,Redux這個的技術棧,我以爲理解的更加的清楚了,固然這僅僅是個人一點點小小的思考,歡迎你們一塊兒討論拍磚,後邊逐步的和你們分享個人心得體會。