redux+express+MongoDB 學習

一肠骆、react 開發(fā)環(huán)境

  • create-react-app 官方腳手架,生成文件格式塞耕,安裝:
cnpm i -g create-react-app
  • 創(chuàng)建一個應用:
create-react-app yjw
  • 進入到 yjw 目錄下:
    • 可以看到自動生成的幾個文件:

README.md蚀腿、package.json、src扫外、node_modules莉钙、public

  • 執(zhí)行命令:npm start
  • 在瀏覽器輸入:localhost:3000
腳手架相關命令:

如何使用 create-react-app :
①npm install --save redux : 安裝第三方庫 redux筛谚;
②npm run eject : 生成配置文件磁玉,可以自定義配置 webpack;
③擴展 package.json 里的 script 字段驾讲,擴展 npm run 命令蚊伞。

二、ES6 簡單介紹

  • ES6 的詳細學習請參照 ES6 的快速入門與使用吮铭。
  • ES6 是新的 JavaScript 語法標準时迫;
  • 使用 babel 語法轉(zhuǎn)換器,使其支持低版本瀏覽器谓晌;
  • 流行的庫基本都是基于 ES6 構(gòu)建掠拳,React 默認使用 ES6 新語法開發(fā)。

1纸肉、塊級作用域溺欧、字符串、函數(shù)

1.1柏肪、塊級作用域
  • 定義變量使用 let 替代 var姐刁;
  • const 定義不可修改的變量;
  • 作用域:{}烦味。
1.2龙填、字符串
  • 模板字符串: 兩個反引號,在兩個反引號之間獲取變量:${變量名}
1.3岩遗、函數(shù)
  • 可以設置參數(shù)默認值扇商;
  • 箭頭函數(shù):
    • 參數(shù)只有一個時,參數(shù)外面的小括號可以省略宿礁;
    • 只有一條 return 語句時案铺,可以省略 return 和大括號;
    • 可以保持 this 作用域梆靖。
  • 展開運算符控汉。

2、對象擴展返吻、解構(gòu)

2.1姑子、對象的擴展:
  • Object.keys、values测僵、entries:
    • keys:獲取到對象 key 組成的數(shù)組街佑;
    • values:獲取到對象 value 組成的數(shù)組;
    • entries:獲取到兩個數(shù)組捍靠,分別有對象的 key 和 value 組成沐旨;
    • 說明:定義一個對象時,鍵可加引號可不加引號榨婆,默認會被認為是一個字符串磁携,如果想要用外面定義的變量作為 key,可按如下方式使用(計算屬性):
const name = 'yijiang';
const person = {
  [name] : 18
};
  • 對象方法簡寫良风,計算屬性:
const obj = {
  hello:function(){//之前寫法},
  hello1(){//現(xiàn)在寫法}
}
  • 展開運算符(不是 ES6 標準谊迄,但是 babel 也支持)
//合并兩個對象
const obj1 = {name:'yijiang',age:18};
const obj2 = {score:100,height:180};
const obj3 =  {...obj1,...obj2};
2.2、解構(gòu)賦值
  • 函數(shù)也可以多返回值了:
    • 數(shù)組解構(gòu)烟央;
    • 對象解構(gòu)统诺。
  • 數(shù)組解構(gòu):
const arr = ['yijiang',18];
const [name,age] = arr;
  • 對象解構(gòu):
const obj = {name:'yijiang',course:'computer'};
const {name,course} = obj;

3、類吊档、模塊化等

3.1 類
  • 提供 class 的語法糖:
    • 是 prototype 的語法糖篙议;
    • extends 繼承唾糯;
    • constructor 構(gòu)造函數(shù)怠硼。
  • ES6 中新出現(xiàn)的數(shù)據(jù)結(jié)構(gòu):
    • Set,元素不可重復移怯;
    • Map香璃;
    • Symbol。
3.2 模塊化
  • ES6 中自帶了模塊化機制舟误,告別 seajs 和 require.js
    • export , export default;
    • import {}葡秒,import;
export 的內(nèi)容,在 import 時眯牧,需要使用 {} 來導入變量名/類名蹋岩;
export default 的內(nèi)容,在 import 時直接導入變量名/類名即可学少。
  • node 現(xiàn)在還不支持剪个,還需要用 require 來加載文件。
3.3 其它:還有一些特性版确,雖然不在 ES6 的范圍扣囊,但是也被 babel 支持,普遍被大家接受和使用(需要安裝插件)
  • 對象擴展符(Babel-plugin-transform-object-rest-spread 插件绒疗,支持擴展符號)侵歇,函數(shù)綁定;
  • 裝飾器吓蘑;
  • async await惕虑。
3.4 其它的特性
  • promise;
  • 迭代器和生成器士修;
  • 代理 proxy枷遂。

三、express + mongodb 基礎

  • express + mongodb 開發(fā) web 后臺接口棋嘲;
  • express 開發(fā) web 接口酒唉;
  • 非關系型數(shù)據(jù)庫 mongodb(存儲類似 json 的數(shù)據(jù));
  • 使用 nodejs 的 mongoose 模塊鏈接和操作 mongodb沸移。

1. express

  • 基于 nodejs痪伦,快速、開發(fā)雹锣、極簡的 web 開發(fā)框架网沾;
  • 安裝: npm install --save express
  • 創(chuàng)建服務器:
//新建一個文件 server.js
const express = require('express');

const app = express();

app.get('/',function(req,res){
  res.send('<h2>Hello World</h2>');
});
//返回 json 數(shù)據(jù)
app.get('/data',function(req,res){
  res.json({name: 'yjw',age: 18});
})
app.listen(3002, ()=>{
  console.log('監(jiān)聽到了端口 3002');
})
//在終端進入到 server.js 所在的文件夾蕊爵,然后執(zhí)行 node server.js 即可啟動服務
//如果對文件中的內(nèi)容進行修改辉哥,必須要先重新啟動才能生效(ctrl + c,node server.js)
//如果想要修改 server.js 中的文件攒射,不進行重啟就使修改的內(nèi)容生效醋旦,可使用插件 nodemon。首先全局安裝 nodemon 插件会放;然后使用 nodemon server.js 進行啟動饲齐;以后刷新瀏覽器頁面即可。
  • 其它的特性:
    • app.get咧最、app.post 分別開發(fā) get 和 post 接口捂人;
    • app.use 使用模塊御雕;
    • res.send(文本)、res.json(json)滥搭、res.sendfile(文件) 響應不同的內(nèi)容酸纲。

2. mongodb + mongoose

  • 非關系型數(shù)據(jù)庫
  • 官網(wǎng) https://www.mongodb.com/ 下載安裝 mongodb买喧;
  • 安裝 mongoose:npm install mongoose --save亿驾;
  • 通過 mongoose 操作 mongodb,存儲的就是 json绕辖,相對 mysql 來說脓诡,要易用很多无午。
2.1. mongoose 的基礎使用
  • connect 鏈接數(shù)據(jù)庫;
  • 定義文檔模型祝谚,schema 和 model 新建模型宪迟;
  • String、Number 等數(shù)據(jù)結(jié)構(gòu)交惯;
  • create次泽、remove、update 分別用來增席爽、刪意荤、改的操作;
  • find 和 findOne 用來查詢數(shù)據(jù)只锻。
//找到 mongodb 安裝目錄玖像,然后在控制臺執(zhí)行 mongo,即可連接上 MongoDB
const express = require('express');
const mongoose = require('mongoose');
// 鏈接 mongoose
const DB_URL = 'mongodb://127.0.0.1:27017';
mongoose.connect(DB_URL);
// 此句測試 是否鏈接成功齐饮,可以刪除
mongoose.connection.on('connected',function(){
  console.log('mongoose 鏈接成功啦~')
})
// 類似于 mysql 的表捐寥,mongo 里面有文檔、字段的概念
const User = mongoose.model('user',new mongoose.Schema({
  name:{type:String,require:true},
  age:{type:Number,require:true}
}))
//增加數(shù)據(jù)
// User.create({
//   name:'mike',
//   age:18
// },function(err,data){
//   if(!err){
//     console.log('增加數(shù)據(jù)成功:',data)
//   }else{
//     console.log('增加數(shù)據(jù)失敗:',err)
//   }
// })
// 刪除數(shù)據(jù)
// User.remove({name:'yijiang'},function(err,data){
//   console.log('刪除數(shù)據(jù)成功:',data)
// })
// 更新數(shù)據(jù)祖驱,$set 可以省略
User.update({name:'mike'},{'$set':{age:28}},function(err,data){
  console.log('更新數(shù)據(jù)成功:',data)
})

// 新建app
const app = express();

app.get('/',function(req,res){
  res.send('<h2>Hello New App</h2>')
})

app.get('/data',function(req,res){
  // 查詢數(shù)據(jù)
  User.find({name:'mike'},function(err,data){ //還有 findOne 方法握恳,該方法返回一個 json
    res.json(data)
  })
})

app.listen(9003,function(){
  console.log('新建 APP')
})
2.2. express + mongodb 實戰(zhàn)(后面講解)
  • mongod --config /usr/local/etc/mongod.conf 后臺啟動;
  • express 結(jié)合 mongodb捺僻;
  • 封裝 mongoose乡洼。
2.3. 后續(xù)進階
  • express 和 mongodb 結(jié)合:
    • mongodb 獨立工具函數(shù);
    • express 使用 body-parser 支持 post 參數(shù)匕坯;
    • 使用 cookie-parser 存儲登錄信息 cookie束昵。

四、React 基礎簡述

  • 這里只是簡單回顧一下 props醒颖、state妻怎、生命周期函數(shù)的相關知識壳炎,詳細學習請參考:React 之高級使用
  • 需要綁定 this 的三種解決方案:
    • ①在 constructor 方法中對方法進行綁定: this.aaa = this.aaa.bind(this)泞歉;
    • ②調(diào)用函數(shù)時逼侦,使用箭頭函數(shù)進行調(diào)用() => this.aaa()
    • ③定義函數(shù)時腰耙,使用箭頭函數(shù)榛丢。
  • 安裝 babel-plugin-import,進行按需加載:
    • 在 package.json 中的 plugins 按需加載:
  "babel": {
    "presets": [
      "react-app"
    ],
    "plugins": [
      ["import",{"libraryName": "antd-mobile","style": "css"}]
    ]
  }
  • 對 props挺庞、state 傳值的簡單使用:
import React,{Component} from 'react'
import {Button, List} from 'antd-mobile'
// import 'antd-mobile/dist/antd-mobile.css'

class App extends Component{
  render(){
    const director = '李云龍';
    return (
      <div>
        <h2>獨立營營長:{director}</h2>
        <Yiying boss='yijiang'/>
        <Erying name='jiang' />
      </div> 
    )
  }
}

// 如果組件只有 render 函數(shù)晰赞,還可以用函數(shù)的形式寫組件
function Erying(props){
  return <h2>二營營長:{props.name}</h2>
}

class Yiying extends Component{
  constructor(props){
    super(props);
    this.state = {soldiers:['虎子','狗子','嘎子']}
  }

  show(e){
    alert(e.target.innerText)
  }

  clickAntButton(e){
    alert(e.target.innerText)
  }

  render(){
    return (
      <div>
        <h2>一營營長:{this.props.boss}</h2>
        <Button type='primary' onClick={this.clickAntButton}>這里是ant Button </Button>
        <List renderHeader='士兵列表' renderFooter='收兵'>
          {this.state.soldiers.map((v,idx) => {
            return (
              <List.Item 
                extra='快來參軍吧' 
                key={idx} 
                onClick={this.show}
                arrow='up'
              >士兵:{v}</List.Item>)
          })}
        </List>
      </div>
    )
  }
}

export default App
  • 生命周期函數(shù)執(zhí)行順序圖:


    生命周期圖.png

五、redux 的使用

1.redux基本概念

  • 是一個專注于狀態(tài)管理的庫:

    • redux 專注于狀態(tài)管理选侨,和 react 解耦掖鱼,也可以和 vue、angular 結(jié)合使用援制;
    • 單一狀態(tài)戏挡,單向數(shù)據(jù)流;
    • 核心概念:store晨仑、state褐墅、action、reducer洪己。
  • redux 的結(jié)構(gòu)可以模仿如下結(jié)構(gòu):


    redux 結(jié)構(gòu).png
  • redux 的使用方法:


    redux 的使用方法
  • 結(jié)合上圖理解以下代碼:

// src/index.js
import {createStore} from 'redux'
// 新建 store
// 通過 reducer 建立妥凳,reducer 根據(jù)老的狀態(tài)和 action 生成新的 state
function counter(state=0,action){
  switch(action.type){
    case '加機關槍':
      return state + 1;
    case '減機關槍':
      return state -1;
    default:
      return 10;
  }
}

//通過 reducer 新建 store
const store = createStore(counter);
const init = store.getState();
console.log('初始化 state:',init); //初始化 state: 10

function listener(){
  const count = store.getState();
  console.log(`現(xiàn)有機槍 ${count} 把。`)
}
// 監(jiān)聽答捕,每次 state 修改都會調(diào)用 listener
store.subscribe(listener)
// 現(xiàn)有機槍 11 把逝钥。
// 現(xiàn)有機槍 12 把。
// 現(xiàn)有機槍 11 把拱镐。

store.dispatch({type:'加機關槍'})
store.dispatch({type:'加機關槍'})
store.dispatch({type:'減機關槍'})
  • 以上代碼中的 subscribe 方法可以進一步優(yōu)化:
store.subscribe(()=>{
  console.log(`現(xiàn)有機槍 ${store.getState()} 把`)
})

2.redux 如何和 react 一起使用

2.1. 手動連接 react 和 redux
圖片.png
  • 個人理解:dispatch(action)時晌缘,會自動將 action 傳給 reducer,然后 reducer 進行相應處理痢站;如果處理中 state 發(fā)生變化磷箕,會觸發(fā) store.subscribe(func)。
  • src 文件夾下有三個文件阵难,內(nèi)容分別如下:
// index.js
import React from 'react'
import {render} from 'react-dom'
import {createStore} from 'redux'

import App from './App'
import {reducer, addGun, removeGun} from './index.redux'

const store = createStore(reducer)

function show(){
  render(
    <App store={store} addGun={addGun} removeGun={removeGun}/>,
    document.getElementById('root')
  )
}

show()

store.subscribe(show)
// App.js
import React from 'react'
import {Button} from 'antd-mobile'

class App extends React.Component{
  render(){
    const {store, addGun, removeGun} = this.props
    return (
      <div>
        <h2>現(xiàn)有槍支:{store.getState()}</h2>
        <Button type='primary' inline onClick={()=>{store.dispatch(addGun())}}>增加槍支</Button>
        <Button type='primary' inline onClick={()=>store.dispatch(removeGun())}>減少槍支</Button>
      </div> 
    )
  }
}

export default App
// index.redux.js
const INCREASE_TYPE = 'INCREASE'
const REDUCE_TYPE = 'REDUCE'

export function addGun(){
  return {type:INCREASE_TYPE}
}
export function removeGun(){
  return {type:REDUCE_TYPE}
}

export function reducer(state=0,action){
  switch (action.type){
    case 'INCREASE':
      return state + 1
    case 'REDUCE':
      return state -1
    default:
      return 10
  }
}
2.2. 處理異步岳枷、調(diào)試工具、更優(yōu)雅的將 react 和 redux 結(jié)合:
  • redux 異步處理呜叫,需要使用 redux-thunk 插件
  • 調(diào)試工具:npm install redux-devtools-extension 并且開啟
  • 使用 react-redux 優(yōu)雅的連接 react 和 redux
2.2.1. redux異步處理:

redux 默認處理同步空繁,異步任務需要 redux-thunk 中間件:

  • npm i --save redux-thunk
  • 使用 applyMiddleware 開啟 thunk 中間件(見下面代碼)
  • action 可以返回函數(shù),使用 dispatch 提交 action
2.2.2. 調(diào)試工具
  • 親測發(fā)現(xiàn)朱庆,只要在 Chrome 瀏覽器中安裝插件 Redux DevTools盛泡;
  • 然后再從 redux 中引入 compose
    • 將原來創(chuàng)建 store 的方式修改一下:
//原來創(chuàng)建 store 的方式
const store = createStore(reducer,applyMiddleware(thunk))
// compose 將函數(shù)組合到一起 , 在 Chrome 中安裝插件 redux 后,將上面創(chuàng)建 store 方式改為如下形式娱颊,在瀏覽器中調(diào)試清晰方便
// 現(xiàn)在創(chuàng)建 store 的方式
const store = createStore(reducer,compose(
  applyMiddleware(thunk),
  window.devToolsExtension ? window.devToolsExtension() : ()=>{}
))
  • 現(xiàn)在 src 文件夾下的代碼如下:
// index.js
import React from 'react'
import {render} from 'react-dom'
import {createStore, applyMiddleware, compose} from 'redux'
import thunk from 'redux-thunk'

import App from './App'
import {reducer, addGun, removeGun, addGunAsync} from './index.redux'

// const store = createStore(reducer,applyMiddleware(thunk))
// compose 將函數(shù)組合到一起 , 在 Chrome 中安裝插件 redux 后傲诵,將上面創(chuàng)建 store 方式改為如下形式凯砍,在瀏覽器中調(diào)試清晰方便
const store = createStore(reducer,compose(
  applyMiddleware(thunk),
  window.devToolsExtension ? window.devToolsExtension() : ()=>{}
))

function show(){
  render(
    <App store={store} addGun={addGun} removeGun={removeGun} addGunAsync={addGunAsync}/>,
    document.getElementById('root')
  )
}

show()

store.subscribe(show)
// App.js
import React from 'react'
import {Button} from 'antd-mobile'

class App extends React.Component{
  render(){
    const {store, addGun, removeGun, addGunAsync} = this.props
    return (
      <div>
        <h2>現(xiàn)有槍支:{store.getState()}</h2>
        <Button type='primary' inline onClick={()=>{store.dispatch(addGun())}}>增加槍支</Button>
        <Button type='primary' inline onClick={()=>{store.dispatch(addGunAsync())}}>遲緩加槍</Button>
        <Button type='primary' inline onClick={()=>store.dispatch(removeGun())}>減少槍支</Button>
      </div> 
    )
  }
}

export default App
// index.redux.js
const INCREASE_TYPE = 'INCREASE'
const REDUCE_TYPE = 'REDUCE'

// action creator
export function addGun(){
  return {type:INCREASE_TYPE}
}
export function removeGun(){
  return {type:REDUCE_TYPE}
} 
//異步
export function addGunAsync(){
  // thunk 插件的作用,這里可以返回函數(shù)
  return dispatch => {
    setTimeout(()=>{
      dispatch(addGun())
    },2000)
  }
}

export function reducer(state=0,action){
  switch (action.type){
    case 'INCREASE':
      return state + 1
    case 'REDUCE':
      return state -1
    default:
      return 10
  }
}
2.2.3. 使用 react-redux
  • 首先安裝插件: npm install --save react-redux
  • 忘記 subscribe拴竹,記住 reducer悟衩,action 和dispatch 即可
  • react-redux 提供 Provider 和 connect 兩個接口來連接
  • 具體使用:
    • Provider 組件在應用最外層,傳入 store 即可栓拜,只用一次
    • connect 負責在組件內(nèi)從外部獲取組件需要的參數(shù)座泳,這時組件內(nèi)不需要顯式觸發(fā)事件(dispatch),直接傳 actionCreator 即可
    • connect 可以用裝飾器的方式來寫
  • src 文件夾下內(nèi)容:
// index.js
import React from 'react'
import {render} from 'react-dom'
import {createStore, applyMiddleware, compose} from 'redux'
import thunk from 'redux-thunk'
import {Provider} from 'react-redux'

import App from './App'
import {reducer} from './index.redux'

const store = createStore(reducer,compose(
  applyMiddleware(thunk),
  window.devToolsExtension ? window.devToolsExtension() : ()=>{}
))

render(
  (
    <Provider store={store}>
      <App />
    </Provider>
  ),
  document.getElementById('root')
)
// App.js
import React from 'react'
import {Button} from 'antd-mobile'
import {connect} from 'react-redux'

import {addGun, removeGun, addGunAsync} from './index.redux'

class App extends React.Component{
  render(){
    const {num, addGun, removeGun, addGunAsync} = this.props;
    return (
      <div>
        <h2>現(xiàn)有槍支:{num} 支</h2>
        <Button type='primary' inline onClick={addGun}>增加槍支</Button>
        <Button type='primary' inline onClick={addGunAsync}>遲緩加槍</Button>
        <Button type='primary' inline onClick={removeGun}>減少槍支</Button>
      </div> 
    )
  }
}

const mapStateToProps = state => {
  return {num:state}
}
const actionCreators = {addGun, removeGun, addGunAsync}
App = connect(mapStateToProps,actionCreators)(App)

export default App
// index.redux.js
const INCREASE_TYPE = 'INCREASE'
const REDUCE_TYPE = 'REDUCE'

// action creator
export function addGun(){
  return {type:INCREASE_TYPE}
}
export function removeGun(){
  return {type:REDUCE_TYPE}
} 
//異步
export function addGunAsync(){
  // thunk 插件的作用幕与,這里可以返回函數(shù)
  return dispatch => {
    setTimeout(()=>{
      dispatch(addGun())
    },2000)
  }
}

export function reducer(state=0,action){
  switch (action.type){
    case 'INCREASE':
      return state + 1
    case 'REDUCE':
      return state -1
    default:
      return 10
  }
}
  • 使用 裝飾器優(yōu)化 connect 代碼:
    • 彈出個性化配置:npm run eject
    • 安裝插件:npm i babel-plugin-transform-decorators-legacy
    • package.json 里 babel 加上 plugins 配置:
"babel": {
    "presets": [
      "react-app"
    ],
    "plugins": [
      [
        "import",
        {
          "libraryName": "antd-mobile",
          "style": "css"
        }
      ],
      "transform-decorators-legacy"
    ]
  },
  • 使用裝飾器挑势,主要是對 connect 進行優(yōu)化:
// App.js
import React from 'react'
import {Button} from 'antd-mobile'
import {connect} from 'react-redux'

import {addGun, removeGun, addGunAsync} from './index.redux'

// const mapStateToProps = state => {
//   return {num:state}
// }
// const actionCreators = {addGun, removeGun, addGunAsync}
// App = connect(mapStateToProps,actionCreators)(App)
@connect(
  state => ({num:state}),
  {addGun, removeGun, addGunAsync}
)
class App extends React.Component{
  render(){
    const {num, addGun, removeGun, addGunAsync} = this.props;
    return (
      <div>
        <h2>現(xiàn)有槍支:{num} 支</h2>
        <Button type='primary' inline onClick={addGun}>增加槍支</Button>
        <Button type='primary' inline onClick={addGunAsync}>遲緩加槍</Button>
        <Button type='primary' inline onClick={removeGun}>減少槍支</Button>
      </div> 
    )
  }
}

export default App

六、react-router4

  • React 官方推薦的路由庫啦鸣,4 是最新版本
    • 4 是全新的版本薛耻,和之前版本不兼容,瀏覽器和 RN 均兼容赏陵;
    • React 開發(fā)單頁應用必備饼齿,踐行路由即組件的概念;
    • 核心概念:動態(tài)路由蝙搔、Route缕溉、Link、Switch吃型。

1证鸥、初識 router4

  • 安裝: npm i --save react-router-dom
  • router4 使用 react-router-dom 作為瀏覽器端的路由
  • 忘掉 router2 的內(nèi)容
1.1、入門組件
  • BrowserRouter勤晚,包裹整個應用枉层;
  • Route 路由對應渲染的組件,可以嵌套赐写,語法:<Route path='/path' component={要渲染的組件}></Route>鸟蜡;
  • Link 跳轉(zhuǎn)專用,語法:<Link to='/path'>展示的名稱</Link>挺邀。
  • 示例:這里只在 index.js 文件中進行添加
// index.js
import React from 'react'
import {render} from 'react-dom'
import {createStore, applyMiddleware, compose} from 'redux'
import thunk from 'redux-thunk'
import {Provider} from 'react-redux'
import {BrowserRouter, Route, Link} from 'react-router-dom'
import App from './App'
import {reducer} from './index.redux'

const store = createStore(reducer,compose(
  applyMiddleware(thunk),
  window.devToolsExtension ? window.devToolsExtension() : ()=>{}
))

function Erying(){
  return <h2>歡迎來到二營</h2> 
}
class Qibinglian extends React.Component{
  render(){
    return <h2>這里是騎兵連</h2>
  }
}

render(
  <Provider store={store}>
    <BrowserRouter>
      <div>
        <ul>
          <li><Link to='/'>一營</Link></li>
          <li><Link to='/erying'>二營</Link></li>
          <li><Link to='/qibinglian'>騎兵連</Link></li>
        </ul>
        <Route path='/' exact component={App}></Route>
        <Route path='/erying' component={Erying}></Route>
        <Route path='/qibinglian' component={Qibinglian}></Route>
      </div>
    </BrowserRouter>
  </Provider>
  ,
  document.getElementById('root')
)
1.2揉忘、其它組件
  • url 參數(shù):Route 組件參數(shù)可用冒號標識參數(shù);
class Test extends React.Component{
  render(){
    console.log(this.props.match.params.location)
    return <h2>測試組件</h2> 
  }
}
===============================
<ul>
  <li><Link to='/'>首頁</Link></li>
  <li><Link to='/erying'>二營</Link></li>
  <li><Link to='/qibinglian'>騎兵連</Link></li>
</ul>

<Route path='/' exact component={App}></Route>
<Route path='/:location' exact component={Test}></Route>

點擊“二營”端铛、“騎兵連”會顯示 Test 組件泣矛,并且可以打印相關的信息,這里會顯示:“erying”禾蚕、“qibinglian”您朽。

  • Redirect 組件:跳轉(zhuǎn);
  • Switch 只渲染一個子 Route 組件换淆。
// index.js
import React from 'react'
import {render} from 'react-dom'
import {createStore, applyMiddleware, compose} from 'redux'
import thunk from 'redux-thunk'
import {Provider} from 'react-redux'
import {BrowserRouter, Route, Link, Redirect,Switch} from 'react-router-dom'
import App from './App'
import {reducer} from './index.redux'

const store = createStore(reducer,compose(
  applyMiddleware(thunk),
  window.devToolsExtension ? window.devToolsExtension() : ()=>{}
))

class Erying extends React.Component{
  render(){
    return <h2>二營</h2>
  }
}

function Qibinglian(){
  return <h2>騎兵連</h2>
}

class Test extends React.Component{
  render(){
    console.log(this.props.match.params.location)

    return <h2>這里應該是 404 頁面喲~ <br/>沒有{this.props.match.params.location}這個路徑喔~</h2> 
  }
}

render(
  <Provider store={store}>
    <BrowserRouter>
      <div>
        <ul>
          <li><Link to='/'>首頁</Link></li>
          <li><Link to='/erying'>二營</Link></li>
          <li><Link to='/qibinglian'>騎兵連</Link></li>
        </ul>

        {/* <Redirect to='/qibinglian' component={Qibinglian}></Redirect> */}
        <Switch>
          {/* Switch 里面只渲染命中的第一個 Route */}
          <Route path='/' exact component={App}></Route>
          <Route path='/erying' component={Erying}></Route>
          <Route path='/qibinglian' component={Qibinglian}></Route>
          <Route path='/:location' component={Test}></Route>
        </Switch>
      </div>
    </BrowserRouter>
  </Provider>
  ,
  document.getElementById('root')
)
  • 復雜的 redux 應用哗总,會遇到多個 reducer 的情況几颜,用 combineReducers 進行合并。

七魂奥、項目開發(fā)

  • 這里不再貼詳細代碼,只列出用到的對應的知識點易猫。詳細代碼可參照項目地址:項目地址

1耻煤、前后端聯(lián)調(diào)

  • 使用 axios 發(fā)送異步請求:
    • 如何發(fā)送,端口不一致時准颓,使用 proxy 配置轉(zhuǎn)發(fā)哈蝇;
    • axios 攔截器,統(tǒng)一 loading 處理攘已;
    • redux 里使用異步數(shù)據(jù)炮赦,渲染頁面;
    • 攔截器:interceptor样勃。

2吠勘、登錄注冊功能的實現(xiàn)

2.1、 頁面文件結(jié)構(gòu)峡眶;
  • 骨架結(jié)構(gòu)實現(xiàn):
    • 組件放在 Component 文件夾下面剧防;
    • 頁面放在 Container 文件夾下面;
    • 頁面入口處獲取用戶信息辫樱,決定跳轉(zhuǎn)到哪個頁面峭拘。
2.2、web 開發(fā)模式狮暑;
  • 基于 cookie 用戶驗證:
    • express 依賴 cookie-parser鸡挠,需要安裝:npm i cookie-parser --save
    • cookie 類似于一張身份卡搬男,登陸后服務器端返回拣展,你帶著 cookie 就可以訪問受限資源;
    • cookie 的管理:瀏覽器會自動處理缔逛。
  • 開發(fā)流程:


    開發(fā)流程
2.3瞎惫、前后端實現(xiàn)。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末译株,一起剝皮案震驚了整個濱河市瓜喇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌歉糜,老刑警劉巖乘寒,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異匪补,居然都是意外死亡伞辛,警方通過查閱死者的電腦和手機烂翰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蚤氏,“玉大人甘耿,你說我怎么就攤上這事「捅酰” “怎么了佳恬?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長于游。 經(jīng)常有香客問我毁葱,道長,這世上最難降的妖魔是什么贰剥? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任倾剿,我火速辦了婚禮,結(jié)果婚禮上蚌成,老公的妹妹穿的比我還像新娘前痘。我一直安慰自己,他們只是感情好担忧,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布际度。 她就那樣靜靜地躺著,像睡著了一般涵妥。 火紅的嫁衣襯著肌膚如雪乖菱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天蓬网,我揣著相機與錄音窒所,去河邊找鬼。 笑死帆锋,一個胖子當著我的面吹牛吵取,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播锯厢,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼皮官,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了实辑?” 一聲冷哼從身側(cè)響起捺氢,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎剪撬,沒想到半個月后摄乒,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年馍佑,在試婚紗的時候發(fā)現(xiàn)自己被綠了斋否。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡拭荤,死狀恐怖茵臭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情舅世,我是刑警寧澤旦委,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站歇终,受9級特大地震影響社证,放射性物質(zhì)發(fā)生泄漏逼龟。R本人自食惡果不足惜评凝,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望腺律。 院中可真熱鬧奕短,春花似錦、人聲如沸匀钧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽之斯。三九已至日杈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間佑刷,已是汗流浹背莉擒。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留瘫絮,地道東北人涨冀。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像麦萤,于是被迫代替她去往敵國和親鹿鳖。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容