在公司用React做項目已經有一年多了,剛開始接觸它的時候,給我的第一感覺就是很有顛覆性,一言不合就往JS里面插入Html代碼。在MVC或者MVVM的框架里,我們宣揚的是視圖V和模型M的分離,就是你負責扮靚,我負責賺錢。而React更多的是宣揚組件化思想,各位看官請看下圖。
那React到底有哪些好處呢?為了方便看官查閱,我在此羅列了出來。
- “輕”;react是很輕量的框架
- 速度快,效率高;真正Dom其實是很巨大的,直接操作Dom很耗性能。React引入virtual dom概念,它不直接操作Dom而是將Dom結構存儲在內存中,然后通過render中返回的內容做一個Dom Diff的比較,再將變化反映到Dom做局部更新。
- 組件化思想;利用React可以輕松構建所需要的組件,并且各組件之間可輕易的組合,使得代碼重用及各模塊之間的測試變得更加簡單。
- 單向式響應數據流;React實現了單向式相應數據流,使得數據交互變得非常簡易清晰,減少了許多重復代碼,比傳統的數據綁定簡單。
那React到底是怎么一回事呢,我們現在來揭開它的神秘面紗,例行慣例先來一段Hello World。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/babel">
ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('example') );
</script>
</body>
</html>
以上的頁面在瀏覽器打開就可以清晰的看到Hello, world!了。以上代碼的最后一個<script>片段要特別注意,它的Type是text/babel,用此標簽的作用是讓babel識別出并最終將jsx語句轉換為瀏覽器可識別可運行的js語句。
上述代碼我們引用了三個庫
react.js:React的核心庫
react-dom.js: 提供與DOM的相關的功能
browser.min.js: 解析jsx語法,將jsx語法轉換為JavaScript語法,實際上這一部很消耗時間應該放在服務器完成
當然你也可以把ReactJs的代碼提取出來,為了讓它看起來有組件的樣子,我們改造成如下樣子。
var HelloWorld = React.createClass({
render: function() {
return (
<h1>Hello, world!</h1>
);
}
});
ReactDOM.render(<HelloWorld/>, document.getElementById("example"));
Html頁面只需要引用它就可以了
<script type="text/babel" src="src/helloworld.js"></script>
需要注意的是,頁面在某些瀏覽器打開可能會報錯無法加載該文件例如谷歌chrome,原因是它不是http請求,如果放在服務器是完全沒有問題的。但我們沒有服務器想在本地看看怎么辦,別急,還是有辦法的。Mac可以先退出瀏覽器再用以下命令打開谷歌chrome。
open -a Google\ Chrome --args --disable-web-security --allow-file-access-from-files --user-data-dir=""
Windows的可以右擊谷歌瀏覽器快捷方式,打開屬性在目標位置后加上如下參數
--args --disable-web-security --allow-file-access-from-files --user-data-dir=""
繼續說上面的代碼,我們可以看到我們使用了<HelloWorld/>給id為example的元素渲染了內容Hello, world!而此時此刻我們所創建的這個React對象就是個簡單的組件了。這里有一點切記組件名字開頭一定要大寫。
現在假如我不想組件返回一個Hello,world給我我想說點別的,比如說洋氣的中文“你好世界”要怎么做呢。這時候我們可以用React的props。
var HelloWorld = React.createClass({
render: function() {
return (
<h1>{this.props.words}</h1>
);
}
});
ReactDOM.render(<HelloWorld words="你好世界"/>, document.getElementById("example"));
props可用于父組件向子組件傳值,這將是組件的一個初始值,一旦設置之后將不能修改。
你可能想父組件在沒有傳值給子組件時,子組件可以有默認的值可以用,這時候這個方法getDefaultProps就派上用場了。該方法是默認給props的各屬性設置相應的值。
var HelloWorld = React.createClass({
getDefaultProps: function(){
return {
words: "你好世界"
};
},
render: function() {
return (
<h1>{this.props.words}</h1>
);
}
});
ReactDOM.render(<HelloWorld/>, document.getElementById("example"));
組件肯定避免不了要與用戶互動,當有數據更新的時候,我們要怎么把新數據渲染到界面上呢。這里我們仍用上一個栗子來闡述這個問題,這時候我們會用到state。
var HelloWorld = React.createClass({
getInitialState: function(){
return {
words: "Hello, world!"
};
},
sayChinese: function(){
this.setState({words: "你好,世界!"});
},
render: function() {
return (
<div>
<h1>{this.state.words}</h1>
<button onClick={this.sayChinese}>Say Chinese!</button>
</div>
);
}
});
ReactDOM.render(<HelloWorld/>, document.getElementById("example"));
同props一樣,state也可以通過getInitialState設置初始值,當用戶點擊組件,調用了方法setState修改了狀態值,導致組件的狀態變化,每次修改完成后都會自動調用render方法重新渲染組件,從這里也可以看出單向數據流的特性。
看起來好像組件都可以調用props的值或者state里的屬性值來展示渲染數據,但其實這兩者是有根本區別的。
props一旦定義就不能改變,state可以隨時改變
props主要組件用于初始化,state用于與用戶交互和組件更新