隨着web應用的發展,前端的比重占得越來越多,編寫代碼從而也越來越復雜。而通常我們需要將不同功能或者不同模塊的代碼分開寫,最后在html中一起加載,這樣做是可以的,但是當你需要進行維護或者是二次開發的時候,你會覺得十分費勁,因為你不知道文件之間復雜的關系,所以我們需要利用一些插件來配合進行模塊化的開發。
所謂模塊化的開發,寫過nodejs的人都知道,文件之間的依賴可以用require()實現,但是瀏覽器端是不支持這樣的依賴形式的,而browserify卻可以解決這個問題,再加上gulp這個強大的構建工具,使得前端的模塊化開發變得簡單了。
接下來就利用gulp和browserify兩個工具,將ReactJs編寫的一個小Demo進行展示:
先來看下我們最終的目錄結構,以便讀者的后續操作:
React是Facebook於2013年開源的一套框架,它從剛開始的UI框架逐漸演變成了新的Web解決方案。它的主要特點有三個:
---Just the UI
---Virtual DOM
---data flow
一個語言的框架,重要的不是記住它的接口,而是要掌握它的思想,要理解並掌握React,需要從這三個特性入手。
Just the UI
沒錯,React在UI上有非常有優勢的地方,這個優勢主要來源於React可以將一個網頁,甚至是一個項目工程的靜態頁面切割成不同的塊,也就是組件。
組件化的開發可以避免模板(如ejs)開發復雜的邏輯,同時它不影響其他框架庫類合並使用,更有利於團隊開發。可見React使開發有了更便捷,使維護更簡單。
Virtual DOM
熟悉前端的人都知道,傳統的DOM渲染及操作是很耗時的,特別是在DOM操作比較頻繁的情況下,DOM是性能出現瓶頸的主要因素。
而React采用虛擬DOM,利用diff算法來進行DOM管理,這里的虛擬DOM其實是保存在內存中,所以速度是非常快的。而且虛擬DOM可以在服務器端渲染,在性能方面這是很有創新的。可見React使網站性能更好。
data flow
React中的數據流與Angular是不同的,或許你認為Angular的雙向數據流對於數據交互非常輕松,但是React基於屬性Props和狀態State的單向數據流會給你帶來條理非常清晰的邏輯,當然你還可以引入其他框架或者庫類來進行與后台的數據交換,這一切的數據都是由組件(React中組件就是一個個狀態機)的屬性和狀態決定。可見React使任務邏輯更清晰。
React是很創新的,對現代工業化前端的開發,維護以及使用的性能都是非常好的提升。還有關於React一些細節就不在這里細說了。
接下來我們開始編寫我們的React Demo。這是一個類似問卷的一個小Demo,包含了3個判斷題的組件的一個頁面,我們最后需要將用戶填寫的結果上傳到服務器,例子很簡單,大家主要要體驗下這個開發過程。
首先在創建一個工程項目:
1.創建一個項目文件夾,並且在sublime text中打開
2.使用cmd進入這個文件夾,然后npm init創建package.json文件,這個文件展示工程的相關信息,包括插件的信息。(前提是要先安裝npm)
3.編寫子組件Child.jsx(判斷題組件),從現在開始我們直接采用模塊化的語法來編寫JSX文件,寫過Node的小伙伴會覺得很熟悉,它其實和服務器端的CommonJs規范是差不多的。有關React的語法可以通過React的官方文檔進行了解。
facebook.github.io/react/index.html >>Learn React Now !

1 var React = require("react/addons"); 2 3 // 判斷題可以看作對和錯只能選一個的題目,因此是一個單選框 4 var Child = React.createClass({ 5 // 狀態對象包含判斷題的當前選項的值 6 // @param : value 7 // @key : true,false 8 getInitialState : function(){ 9 return{ 10 value : "true" 11 }; 12 }, 13 handleChange : function(event){ 14 //通過事件委托連接子組件和父組件,將子組件中的value狀態傳入到父組件中 15 if(this.props.onChange){ 16 this.props.onChange(event); 17 } 18 //更改子組件的狀態,重新渲染UI上。 19 this.setState({ 20 value : event.target.value 21 }); 22 }, 23 render : function(){ 24 return( 25 <div> 26 <label>{this.props.label}</label> 27 <input type="radio" name={this.props.name} checked={this.state.value == "true"} value="true" onChange={this.handleChange} /> 28 "true" 29 <input type="radio" name={this.props.name} checked={this.state.value == "false"} value="false" onChange={this.handleChange} /> 30 "false" 31 </div> 32 ) 33 } 34 }); 35 36 module.exports = Child;
4.編寫父組件Parent.jsx(提交組件)。

1 var React = require("react/addons"); 2 var Child = require("./Child.jsx"); 3 4 var Parent = React.createClass({ 5 getInitialState : function(){ 6 return{ 7 //題目編號 8 name : ["judge-1","judge-2","judge-3"], 9 //題目名稱 10 label : ["do you think yxy is handsome?", 11 "do you like this boke?", 12 "do you want to know React?" 13 ], 14 //用戶默認選項 15 value1 : "true", 16 value2 : "true", 17 value3 : "true" 18 } 19 }, 20 handleChange : function(value,event){ 21 var newState = {}; 22 //通過子組件傳過來的value改變當前父組件的value 23 newState[value] = event.target.value; 24 //設置新狀態 25 this.setState(newState); 26 }, 27 handleSubmit : function(event){ 28 //取消提交默認事件 29 event.preventDefault(); 30 //打印父組件存放的數據 31 console.log(this.state); 32 }, 33 render : function(){ 34 var renderChilds = []; 35 renderChilds = this.state.name.map(function(value,index){ 36 return( 37 <Child name={this.state.name[index]} label={this.state.label[index]} onChange={this.handleChange.bind(this,"value"+(index+1))}></Child> 38 ); 39 }.bind(this)); 40 return( 41 <form onSubmit={this.handleSubmit}> 42 {renderChilds} 43 <button type="submit">提交</button> 44 </form> 45 ); 46 } 47 }); 48 49 module.exports = Parent;
5.最后的出口文件app.jsx。

1 var React = require("react/addons"); 2 var Parent = require("./Parent.jsx"); 3 4 React.render(<Parent></Parent>,document.body); 5 Perf = React.addons.Perf;
6.目前為止我們工程的目錄如下:
React編寫告一段落。
什么是Gulp
Gulp是一個基於流的自動化構建工具,需要注意兩點,一為自動化,二為流。
在Gulp之前又一款名為Grunt的工具拉開了前端自動化的帷幕。所謂自動化,就是自動幫你完成一些工程中需要我們去手動完成的一些重復繁瑣的操作,簡單的比如預處理,壓縮,合並文件等等。而"流",代表着Gulp通過IO流的通道高效地進行自動化任務,前面提到的Grunt是與之相反,它沒進行一次任務都會打開一次IO通道,任務耗時自然沒有Gulp好。
了解Grunt -> 官網 : http://gruntjs.com/ 中文官網 : http://www.gruntjs.net/
了解Gulp -> 官網 : http://gulpjs.com/ 中文官網 : http://www.gulpjs.com.cn/
安裝Gulp
安裝及項目使用過程在官網都有介紹,這里再簡單說一下。
1.全局安裝Gulp
npm install -g gulp
2.作為項目的開發依賴安裝
npm install gulp --save-dev
如何使用Gulp管理文件
1.創建gulpfile.js文件於項目根目錄,在其中編寫我們的任務代碼。
var gulp = require('gulp'); gulp.task('default', function() { // 將你的默認的任務代碼放在這 });
2.在gitBash或者其他窗口命令中執行任務
gulp
關於Gulp
Gulp的學習非常簡單,反復練習幾次你就會發現Gulp的方便之處~
上一點中,我們知道了gulp是一款非常強大的自動化構建工具,然而我們最開始也提到了瀏覽器中是不能直接解析類似require()這樣的語法的。所以我們需要Browserify這個強大的工具。
什么是Browserify
Browserify 可以讓你使用類似於 node 的 require() 的方式來組織瀏覽器端的 Javascript 代碼,通過預編譯讓前端 Javascript 可以直接使用 Node NPM 安裝的一些庫。
了解Browserify -> 官網 : http://browserify.org/
安裝Browserify
安裝Browserify和安裝Gulp是一樣的簡單。
1.全局安裝Browserify
npm install -g browserify
2.作為項目的開發依賴安裝
npm install browserify --save-dev
如何使用Browserify
1.利用Browserify解決require()依賴問題,將app.js中所有依賴項加載並整合到goal.js中。html只要加載goal.js即可。
browserify app.js > goal.js
關於Browserify
Browserify解決了js在瀏覽器端的依賴問題,但是還有一個更為強大的工具名曰webpack!它可以將js,css,png等很多文件的依賴問題解決,而Browserify只能解決js。但已經足夠強大,有關webpack的內容我和大家都還需要慢慢去了解。
終於到了激動人心的時候,現在我會結合前面兩個工具來進行前端模塊化開發的模擬。
1.包含所有依賴到node_modules文件中,package.json中會出現對應依賴項。
1.1 React框架.
npm install react --save-dev
安裝React是為了使我們編寫的React組件能夠順利使用。
1.2 Gulp工具.
npm install gulp --save-dev
安裝Gulp方便自動化構建我們的文件
1.3 Browserify工具
npm install browserify --save-dev
安裝Browserify解決js依賴問題。
*1.4 reactify工具
npm install reactify --save-dev
將jsx編譯為js,類似與JSXTransform.js。
*1.5 react-tools工具
npm install react-tools --save-dev
*1.6 vinyl-source-stream工具
npm install vinyl-source-stream --save-dev
這個要着重說一下,使用gulp時,你可能會陷入“流不兼容”的問題。這主要是因為常規流和Vinyl文件對象有差異,或是使用了僅支持buffer(不支持流)庫的gulp插件與常規流不兼容。
如果我們需要將gulp和(或)gulp插件與常規的可讀流一起使用,我們就需要先把可讀流轉換為vinyl。
如果實在不能理解,可以取百度Google更多資料,推薦看看這篇文章 : http://segmentfault.com/a/1190000000711469
2.編寫gulpfile.js文件
在編寫之前要明確我們的目的 ->將所有的jsx及jsx所依賴的js文件合並到一個新的js文件中
因此gulpfile.js文件如下 :

1 var gulp = require("gulp"); 2 var browserify = require("browserify"); 3 var source = require("vinyl-source-stream"); 4 var reactify = require("reactify"); 5 6 7 //gulp主動設置的命令 8 gulp.task("combine",function(){ 9 //通過browserify管理依賴 10 browserify({ 11 //入口點,app.jsx 12 entries : ["./app.jsx"], 13 //利用reactify工具將jsx轉換為js 14 transform : [reactify] 15 }) 16 //轉換為gulp能識別的流 17 .bundle() 18 //合並輸出為app.js 19 .pipe(source("app.js")) 20 //輸出到當前文件夾中 21 .pipe(gulp.dest("./")); 22 }); 23 24 25 //gulp默認命令 26 gulp.task("default",["combine"]);
3.執行gulp命令
4.查看我們的目錄結構
5.打開index.html
6.執行4次提交操作,觀察數據是否正確顯示
7.可以看到value1,value2,value3的值隨我們的不同提交而改變。
總結:
前端如今已經步入工業化的時代,結合多樣的工具可以讓我們更高效地進行開發,當然現在的前端工具仍處於不穩定的階段,但我們也需要不斷的摸索,從grunt到gulp,再到當下最火的webpack,前端多樣化的工具的更新迭代從未停下腳步,因此我們更不應該停止學習的腳步。
同樣的,gulp+browserify的開發模式可能會隨着前端的浪潮逐漸被埋沒,但它的思想是永恆的,我們要做的便是拋下浮躁,去探索更好的開發模式。