使用React 應當注意的幾個地方

AnnatarHe發表於2015-12-06

目標人群

獻給熟悉基礎的React語法的剛接觸React的同學~

如果你已經寫過半年以上的React那也不用看了,畢竟我水平並不高

What`s React

React 是一個不存在的網路公司Facebook出的JavaScript檢視框架。

他們官網寫著

JUST THE UI

VIRTUAL DOM

DATA FLOW

這三個特性。

當我第一次看到的時候在想,這丫的弱爆了,人家動輒就MVCMVVM的框架,你竟然只寫了一個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都是未來要研究的東西。

好好學習吧,少年~

相關文章