目標人群
獻給熟悉基礎的React語法的剛接觸React的同學~
如果你已經寫過半年以上的React那也不用看了,畢竟我水平並不高
What`s React
React 是一個不存在的網路公司Facebook出的JavaScript檢視框架。
他們官網寫著
JUST THE UI
VIRTUAL DOM
DATA FLOW
這三個特性。
當我第一次看到的時候在想,這丫的弱爆了,人家動輒就MVC,MVVM的框架,你竟然只寫了一個UI?
當然,當時我的想法肯定是錯的。
React擁有非常高的效能,結合單向資料流還有元件化思想,可以很舒服的做出現代化的前端產品。
Start
首先,得有開發環境。
Node的安裝推薦用nvm,我在上一篇《編譯我的開發環境》裡有寫。
主要是在專案裡得加入編譯jsx到正常的js
$ npm install --save gulp browserify babelify vinyl-source-stream babel-core
在gulpfile.babel.js
里加上任務
import gulp from `gulp`;
import browserify from `browserify`;
import babelify from `babelify`;
import source from `vinyl-source-stream`;
gulp.task(`jsx`, () => {
return browserify(`src/app.js`)
.transform(babelify.configure({
stage:0
}))
.bundle()
.pipe(source(`bundle.js`))
.pipe(gulp.dest(`dist/`));
});
這樣,開發環境就大功告成了。
然而,然而。
起初的時候要寫React這種程式碼是比較痛苦的。
平常就是寫HTML,然後主要通過jQuery調整頁面,完成一些顯示的功能。
而React是強迫元件化,強制性的用元件化來構造前端。
這裡寫我的Live template吧,直接複製貼上到WebStorm就可以啦
import React from `react`;
class $className$ extends React.Component {
render() {
return (
$content$
);
}
}
export default $className$;
ES2015
看到這裡,如果同學你不熟悉ES2015的語法可能就感覺看不懂這是什麼了,這還是JavaScript麼?
如果真的對ES2015語法不太熟悉,可以看看阮一峰老師的書:ECMAScript 6入門
我非常的喜歡ES6的語法,因為寫起來非常的清晰明瞭。看著舒服。
只是絕大部分瀏覽器現在並不能完全支援ES6,所以需要babel轉義。
上面的gulp的jsx task就是完成這樣的轉義。
Spelling Component
這個問題和中文有關。
當初我因為英文不過關,老是把Component
寫成Components
或者component
或者components
。
這幾種都是不行的。都會造成錯誤,注意一定一定嚴格的用Component
,所以我建議直接複製我的Live template。
Use strict
其實挺糾結的。因為用babel的話他會轉義程式碼,寫不寫`use strict`其實一個樣。
然而我還是建議加上`use strict`。
如果放棄babel,那麼我們也可以寫出嚴格的js程式碼,這樣多好。
bind(this)
這裡有些很奇怪的問題。有一些情況下這樣寫會出錯
class App extends React.Component {
handleChange(e) {
console.log(this);
}
render() {
return (
<input type="text" onChange={this.handleChange} />
);
}
}
對,這個this,有時候不知道為什麼this指向就會變。
如果你碰到了這樣的問題,可能加一個繫結當前this會有效:
<input type="text" onChange={this.handleChange.bind(this)} />
這個問題並沒有深究,留待再碰到再解決吧。
Ajax
不可避免的,構建SPA肯定是要用到Ajax的。
我有時候也想用fetch
,但是,這次我慫了。 瀏覽器相容性實在是太差了。
chrome 42 才支援。不能指望其他瀏覽器跟上了。
言歸正傳,一般情況下Ajax資料是要傳到state
裡面的,所以一般是這樣的:
class App extends React.Component {
fetchSomething() {
$.ajax({
url: `http://foo.com`,
dataType: `json`,
method: `GET`,
success: function(res) {
this.setState({ res: res });
}
});
}
render() {
return (...);
}
}
如果你真的這樣寫,恭喜你,你會碰到兩個坑!
一個是this
,在success中的this指向可是XMLHttpRequest的物件哦,並不是App 的class。這個時候一般用的是在外面儲存this,然後裡面呼叫
let that = this;
that.setState({});
第二個坑更隱蔽。我當初愣是沒想起來。
非同步
即使經常寫原生js也很容易忽視這個問題。
ajax請求預設是非同步的,也就是說,資料尚未傳送到客戶端的時候,js就已經跑完了客戶端的所有程式碼(好幾遍)。V8那個效率,你懂的。
問題來了。資料沒有到,那麼this.setState也就沒有觸發,那麼後面用資料怎麼辦?
GG
好了,既然原理知道了,那麼解決方法也就很簡單了,在Ajax請求的時候改成同步的
$.ajax({
url: `/foo/bar`,
dataType: `json`,
async: false,
success: function(res){
this.setState({res});
}
});
這裡也就造成了一個問題,Ajax請求在了主執行緒上。網路堵塞就完蛋了。。。額,再說吧。
constructor
constructor是ES6的class的建構函式,在React中用處非常的大
class App extends React.Component {
constructor(props) {
super(props);
// do something
this.state = {
author: `Annatar`
}
}
render() {
return (...);
}
}
建構函式必須傳入props,並且在第一行就得首先呼叫父類的建構函式。
state的設定在constructor中並不是setState了,而是變成了賦值。就像上面的那樣
我就在constructor中呼叫Ajax。。。
Props
這個是深坑啊。埋了我好長時間。。。
你要是老老實實跟著官網寫props,就像這樣
class App extends React.Component {
static PropTypes = {
url: React.PropTypes.string.isRequired
}
static defaultProps = {
url: `/foo/bar`
}
render() {
return (...);
}
}
哈哈,正常情況是會報錯的!
我經過查資料才得知static
目前是ES7
草案上的屬性,但是React官方已經推薦用了。
預設的babel並沒有開啟ES7的轉義。所以會報錯,不認識。
所以我在gulp配置檔案中把babelify的stage改成了0.表示所有屬性都用,
然後就通過了
React-dom
我目前碰到的最深的坑,沒有之一。
我記得之前的寫法是React.render(<App />, document.body)
,嗯,挺正常的。好
後來升級到0.14.0,要引入react-dom,寫成這樣也挺好的:
import ReactDOM from `react-dom`;
import App from `./app`;
ReactDOM(<App />, document.body);
嗯,挺好的。看著不錯嘛。
但是。。。為毛小版本的升級0.14.2就要換成ReactDOM.render
!
最坑的是react-router
這個專案裡面的readme裡寫的是錯誤的寫法!(現在是正確的)
我當時困惑了足足兩個小時。後來哪裡都確定了沒有問題。就是找不出原因,後來就輸出ReactDOM才發現裡面丫的藏著一個render方法。這才正確。
一定記得,多看文件。注意,注意,注意,千萬只看官方的文件,其他的誰都不可靠!
import ReactDOM from `react-dom`;
// import {render} from `react-dom`; 也行
import App from `./app`;
ReactDOM.render(<App />, document.body);
// render(<App />, document.body);
react-router
上面講了react-router的坑爹文件。這裡得說說react-router的坑爹版本號
安裝的時候千萬別懶省事,不然就直接拷貝:
$ npm install --save history react-router@latest
我當時就是懶得打最後的@latest
,導致怎麼都沒辦法顯示效果。也是找了大半天的問題。後來才發現Router是undefined
別懶省事就成了。
Others
關於Flux理解不夠深,也沒有用。
反正我現在看到react-router
就後背涼颼颼的。Redux
也是這老大做的吧。感覺菊花一緊。。。
下一步
從一開始的彆扭,到現在不寫React的彆扭,轉變其實還是蠻大的。
關於React的探索,這裡並不是終點。
其他的,動畫,Flux,React-Native,Meteor都是未來要研究的東西。
好好學習吧,少年~