React + Node 單頁應用「一」前端搭建

項目地址
預覽地址
原文地址javascript

記錄最近作的一個 demo,前端使用 React,用 React Router 實現前端路由,Koa 2 搭建 API Server, 最後經過 Nginx 作請求轉發。css

這是第一篇,主要介紹下前端代碼的構建、React router 使用中遇到問題,以及前端開發完成後部署相關工做。html

功能介紹

GitCard 能夠經過 GitHub 受權獲取用戶基本信息前端

  • 在首頁模塊,能夠查看最近登陸的用戶,並點擊頭像查看該用戶的詳細信息
  • /Comment 模塊中能夠發表評論,並刪除本身的評論
  • /Detail 模塊中能夠查看用戶在 Github 上的基本信息(代碼庫,Follower、Following 以及更多開發的信息),你能夠在這個基礎上作更多有意思的事情,支持 Follow 和 Unfollow 操做,固然,你能夠加上 Star 和 Unstar 操做,殊途同歸。🈳️

依賴版本

  • 構建工具: create-react-app
  • react: 16.0.0
  • react-router: 4.2.2
  • 網絡請求: axios
  • UI: material-ui

項目搭建

前端構建工具使用 React 官方的 create-react-app,快速生成可執行的項目結構。下面是快速上手流程,詳細的內容能夠參見 官方文檔java

// 全局安裝 create-react-app
npm install -g create-react-app

//生成項目,項目名 my-app(自定義)
create-react-app my-app
cd my-app

// 安裝依賴
npm install
// 開發環境
npm start
// 打包
npm run build

生成項目後,項目文件結構以下,npm run build 執行後,目錄下會出現 /build/ 目錄,存放構建後的文件。node

/**
 * my-app 目錄結構
 */
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public 
│   └── favicon.ico
│   └── index.html
│   └── manifest.json
└── src
    └── App.css
    └── App.js //項目入口
    └── App.test.js
    └── index.css
    └── index.js
    └── logo.svg
    └── registerServiceWorker.js

咱們在 /src/ 目錄下新建 /components/ 目錄,用於存放本次項目中的全部自定義組件,最終的目錄以下react

.
├── README.md
├── build
├── package.json
├── public
├── src
│   ├── App.css
│   ├── App.js
│   ├── App.test.js
│   ├── components
│   │   ├── Comments
│   │   │   ├── comment.css
│   │   │   └── index.jsx
│   │   ├── Events
│   │   │   └── index.jsx
│   │   ├── HomePage
│   │   │   └── index.jsx
│   │   ├── UserDetail
│   │   │   └── index.jsx
│   │   └── layouts
│   │       ├── Header.jsx
│   │       └── SideMenu.jsx
│   ├── index.css
│   ├── index.js
│   ├── logo.svg
│   ├── registerServiceWorker.js
│   └── utils
│       ├── api.jsx
│       ├── fetch.jsx
│       └── keygen.js
└── yarn.lock

前端路由

此次作的項目是單頁應用,經過 React router 實現前端路由,Container 經過路由選擇顯示的模塊內容,在 Header 顯示路由切換入口,頁面結構圖以下。ios

/src/App.js 佈局並設置路由,將 HeaderContainer 包在 Router 下,在 Header 的 Menu 組件中設置路由連接,並在 Container 中設置路由指向對應組件。git

Menu 中 Detail 連接在用戶受權登陸後就指向登陸用戶信息,不然跳轉到受權登陸頁面。github

// 引入 React router
import {
  BrowserRouter as Router,
  Link,
  Route
} from "react-router-dom"

// 在 layout-content 中設置路由對應的組件
<Router>
    <div className="App">
        <Header loginInfo={this.state.loginInfo}></Header>
        <div className="layout-container">
            <div className="layout-content">
                <Route exact path="/" component={ HomePage } ></Route>
                <Route path="/user/:userid" component={ UserDetail } ></Route>
                <Route path="/events" component={Events}></Route>
                <Route path="/comments" render={ ()=><Comments loginInfo={this.state.loginInfo} /> }></Route>
            </div>
        </div>
    </div>
</Router>

// 在 Header 中設置 Link 
<Menu>
    <Link to="/">
        <MenuItem primaryText="Home" />
    </Link>
    <Link to="/comments">
        <MenuItem primaryText="Comments"/>
    </Link>
    {
    this.props.loginInfo.login ?
      (<Link to={  '/user/' + this.props.loginInfo.login }>
            <MenuItem primaryText="Detail" />
      </Link>)
      : (<MenuItem primaryText="Login" onClick={this.login} />)
    }
</Menu>

數據操做

路由下發數據

上面的代碼的路由中,咱們經過兩種方式下發數據到組件中,經過路由參數將用戶 ID 下發到 Detail 組件,以及經過 props 講用戶基本信息下發到 Comment 組件中。

// 經過路由參數下發的 Link 以及對應的 Route
<Link to={  '/user/' + this.props.loginInfo.login }><MenuItem primaryText="Detail" /></Link>
<Route path="/user/:userid" component={ UserDetail } ></Route>

// 經過 props 下發
<Route path="/comments" render={ ()=><Comments loginInfo={this.state.loginInfo} /> }></Route>

經過路由參數獲取下發數據,若是在 /user/lijundong 跳轉到 /user/free-free 會出現路由改變,數據不刷新的狀況,這裏須要用 componentWillReceiveProps(nextProps) 處理。

Detail 組件中獲取 ID,

const userId = this.props.match.params.userid;

以及在 Comment 中獲取用戶信息

const loginInfo = this.props.loginInfo;

數據請求

咱們在這裏選擇用 axios 網絡請求,爲了方便管理,將全部的 API 統一放在 /src/utils/api.jsx 中,利於後期維護。
沒有使用 Fetch 是由於 Github API 只支持 XHR 跨域請求,Fetch 跨域請求會致使請求 request type 變成 option

數據更新

setState

由於此次的數據並不複雜,因此沒有引入 MobX 或者 Redux 處理,數據更新全程使用 setState,不過因爲 setState 是異步操做,因此,某些狀況下,須要用到回調函數,以下

setState(
  { name: "Michael" },
  () => console.log(this.state.name)
);
// Michael

componentWillReceiveProps

上面提到過,經過路由參數獲取下發數據,若是在 /user/lijundong 跳轉到 /user/free-free 會出現路由改變,數據不刷新的狀況,這是由於 componentDidMount() 只會執行一次,props 更新不會觸發從新獲取數據,這裏可經過 componentWillReceiveProps() 解決。

componentWillReceiveProps() 會在每次 props 更新時觸發,經過新參數從新獲取數據列表。

componentWillReceiveProps(nextProps){
    const userId = nextProps.match.params.userid;
// 經過新參數獲取數據
    Axios.get(url)
}

項目構建部署

項目開發結束,經過 npm run build 進行打包,打包完成後,生成的 /build/ 即咱們最終上線的版本,由於是先後端分離的項目,前端須要自起 Server,能夠經過這兩種方案進行部署

  • 使用 create-react-app 自帶的 serve -s build 命令起 Server(我當前使用的方式)
  • 或者經過第三方工具 http-serveranywhere 等起 Server

服務開啓後,能夠正常訪問就表明前端部分已經完成,暴露的端口供最後 Nginx 配置使用。

相關文章
相關標籤/搜索