Redux+React Router+Node.js前期配置-1


運(yùn)行之前首先要啟動(dòng)mongodb (提醒:在win+r cmd內(nèi)運(yùn)行)

第一步開啟mongodb服務(wù)器:
D:\mongodb\bin\mongod --dbpath d:\data\db
第二步打開mongodb服務(wù)
D:\mongodb\bin\mongo.exe
//開啟9993端口
$ node server.js


用過React就知道.React就是針對(duì)于View層的一個(gè)庫.

單純的React在做復(fù)雜應(yīng)用是比較吃力的.所以React在做復(fù)雜的應(yīng)用是離不開官方的推薦的Redux(狀態(tài)管理庫).由于Redux上手比較困難.因?yàn)镽edux中dispatch action reducer state 單身邊數(shù)據(jù)流 都是比較吃力的.

做什么?
有實(shí)時(shí)聊天功能的招聘APP,接口都是真實(shí)的接口.
那些功能?
登錄注冊(cè),信息完善,個(gè)人中心,牛人列表,BOSS列表,消息列表,聊天詳情頁.
技術(shù)棧?
React全家桶
前端支持:
antd-mobile Redux狀態(tài)管理 React-router4 axios異步請(qǐng)求 create-react-app 第三方組件 React
后端支持:
Express Socket.io (聊天實(shí)時(shí)通訊)
Mongdb(存儲(chǔ))

搭建環(huán)境:
1.create-react-app
2.如何安裝和使用第三方庫
3.如何定制化配置

image.png

$cnpm install redux --save-dev 安裝redux
$cnpm run start 啟動(dòng)
$ cnpm run eject 將它的配置彈出來

ES6語法:
解構(gòu)賦值:
函數(shù)也可以多返回值了

  1. 數(shù)組解構(gòu)
  2. 對(duì)象解構(gòu)
image.png
image.png

提供類的語法糖
是prototype的語法糖
Extends繼承
Constructor構(gòu)造函數(shù)

image.png

ES6新出現(xiàn)的數(shù)據(jù)結(jié)構(gòu)
Set , 元素不可重合
Map
Symbol

模塊化
Import import{}
Export ,Export default
Node現(xiàn)在還不支持,還需要用require來加載文件.
ES6自帶了模塊化機(jī)制 告別seajs和require.js


image.png

裝飾器
Async await

其他特性
Promise
迭代器和生成器
代理Proxy

image.png

Express + mongodb
Express + mongodb開發(fā)web后臺(tái)接口
Express開發(fā)web接口
非關(guān)系型數(shù)據(jù)庫mongodb 存儲(chǔ)的是類似于json的數(shù)據(jù).

使用nodejs的mongoose模塊鏈接和操作mongodb

Express基于nodejs,快速,開發(fā),極簡(jiǎn)的web開發(fā)框架.
$: cnpm install express --save-dev 安裝express
express最簡(jiǎn)單的使用:
server.js

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

app.get('/',function(req,res){
    res.send('<h1>Hello World</h1>');
})

app.listen(9993,function() {
    console.log('Node app start at port 9993');
})

啟動(dòng)express
進(jìn)入server.js目錄下
$:node server.js


image.png

image.png

如果遇見


image.png

將$:node server.js 重新跑一下
server.js

app.get('/data',function(req,res){
    res.json({name:'bin',age:20});
})
image.png

解決一個(gè)問題:
每次修改完server.js以后我們都需要手動(dòng) control + c 然后再node server.js 這樣繁瑣.
解決:
安裝:$ cnpm install nodemon -g

然后不在用
$node server.js
而用:

$nodemon server.js

Express使用


image.png

當(dāng)我們的模塊復(fù)雜以后,我們使用模塊 app.use


res.send res.json res.sendfile響應(yīng)不同的內(nèi)容

Mongodb + mongoose
非關(guān)系型數(shù)據(jù)庫
官網(wǎng) [圖片上傳失敗...(image-8928a5-1524225217093)] 下載安裝mongodb

image.png

mongodb與express配合時(shí)候最好的一個(gè)庫是mongoose

image.png

安裝mongoose
$: cnpm install mongoose --save-dev

啟動(dòng)mongodb(教程看的是菜鳥教程-mongodb)
是菜鳥教程-mongodb

第一步開啟mongodb服務(wù)器:
D:\mongodb\bin\mongod --dbpath d:\data\db
第二步打開mongodb服務(wù)
D:\mongodb\bin\mongo.exe

如何使用這個(gè)庫:
例子
server.js

//連接mongodb
const DB_URL = 'mongodb://localhost:27017';
mongoose.connect(DB_URL);

//如果連接成功打印一個(gè)字符串
mongoose.connection.on('connected',function(){
    console.log('mongo connect success!!');
})

運(yùn)行這個(gè)腳本(在server目錄下)

nodemon server.js
n

mongodb里面是一個(gè)集合或者說文檔.如何用

//如果沒有這個(gè)immoc它會(huì)自己生成一個(gè)
const DB_URL = 'mongodb://localhost:27017/immoc';

mongoose操作mongodb,存儲(chǔ)的就是json,相對(duì)于mysql來說,要易用很多.

image.png
image.png

新增數(shù)據(jù)

//類似于mysql的表,mongo里有文檔,字段的概念
const User = mongoose.model('user',new mongoose.Schema({
    user : { type: String, require: true },
    age : {type:Number,require:true}
}))
User.create({
    user : 'zhangbin',
    age : 20
},function (err,doc) {
    if(!err){
        console.log(doc);
    } else {
        console.log(err); 
    }   
})
增加成功
image.png

mongoose基本操作

const express = require('express');
const mongoose = require('mongoose');

//連接mongodb 并且使用imooc這個(gè)集合 如果沒有這個(gè)集合會(huì)自動(dòng)給我們建
const DB_URL = 'mongodb://localhost:27017/imooc';

mongoose.connect(DB_URL);

//如果連接成功打印一個(gè)字符串
mongoose.connection.on('connected',function(){
    console.log('mongo connect success!!');
})

//類似于mysql的表,mongo里有文檔,字段的概念
const User = mongoose.model('user',new mongoose.Schema({
    user : { type: String, require: true },
    age : {type:Number,require:true}
}))

更新數(shù)據(jù)
User.update({'user':'xiaoming'},{'$set':{'age':32}},function (err,doc) {
    console.log(doc);
})
  
刪除數(shù)據(jù)
User.remove({user : 'binbin'},function (err,doc) {
    console.log(doc);
})
 
User.create({
    user : 'binbin',
    age : 20 
},function (err,doc) {
    if(!err){
        console.log(doc);
    } else {
        console.log(err);  
    }   
})

回顧React基礎(chǔ)知識(shí)
React是什么?
使用React實(shí)現(xiàn)組件化
React進(jìn)階使用

React是什么?
幫助你構(gòu)建UI庫,其實(shí)就是常說的mvc中的view庫.
一切皆是組件
全部是使用ES6語法,最新版本16

React是什么?
render返回的值是輸出JSX語法,會(huì)把JSX轉(zhuǎn)成js執(zhí)行.
class寫成classname
變量要用{}包裹

同時(shí)可以在一個(gè)js文件寫2個(gè)類

import React from 'react';
class App extends React.Component {

  render(){
    const name = 'bin';
    return (
      <div>
        <h1>superman:{name}</h1>
        <HH></HH>
      </div>

    );
  }
}

class HH extends React.Component {

  render() {
    const name = 'Gao';
    return (
      <h1>superman:{name}</h1>
    );
  }
}

export default App;
image.png
image.png
image.png
image.png
image.png

我們?cè)陂_發(fā)的時(shí)候應(yīng)該使用一個(gè)chrom提供給我們的插件:


image.png

antd-mobile組件庫
螞蟻金服出品的UI組件庫
安裝

$ cnpm install antd-mobile --save-dev

解釋: $ cnpm install antd-mobile@next --save-dev 這個(gè)是安裝最新版的

按需加載:安裝插件

$ cnpm install babel-plugin-import --save-dev

app.js

import React from 'react';
import {Button} from 'antd-mobile';
// import 'antd-mobile/dist/antd-mobile.css'; 這個(gè)不在需要

package.json

在
  "babel": {
    "presets": [ 
      "react-app"
    ],
    "plugins" : [
      ["import", {"libraryName":"antd-mobile","style":"css"}]
    ]
  },
增加
    "plugins" : [
      ["import", {"libraryName":"antd-mobile","style":"css"}]
    ]

于是就是按需加載了

并且react-native也是用的這個(gè)antd-mobile UI庫
兼容Web和ReactNative

常用的組件:
Import后可以直接使用
Layout布局組件
表單組件 數(shù)據(jù)展示組件 選擇器
操作組件

Redux基礎(chǔ)知識(shí)
Redux是什么?
Redux核心概念?
Redux實(shí)戰(zhàn)

Redux是什么?
Redux是專注于狀態(tài)管理的庫
Redux專注狀態(tài)管理和react解耦.
單一狀態(tài),單向數(shù)據(jù)流.

核心概念:store state action reducer

我們來拿李云龍的獨(dú)立團(tuán)來說:
人少的時(shí)候,無論兵器和人員的變更,都是setState
發(fā)展為千人大團(tuán)時(shí)候,老李決定,軍事和生活分開.

所有狀態(tài)歸為趙政委管理(redux)管理, 自己只打仗(view顯示)

趙政委(redux)有什么能力?
老趙有一個(gè)保險(xiǎn)箱(store),所有人的狀態(tài),在哪里都有記錄(state)
需要改變的時(shí)候,需要告訴專員(dispatch)要干什么(action)
處理變化的人(reducer)拿到state和action,生成新的state.

走馬上任
首先通過reducer新建store,隨時(shí)通過store.getState獲取狀態(tài).
需要狀態(tài)變更,store.dispatch(action)來修改狀態(tài)
Reducer函數(shù)接收state和action,返回新的state,可以用store.subscribe監(jiān)聽mei每次修改.

Redux獨(dú)自最基本的使用

import { createStore } from "redux";

//新建store
//通過reducer建立
//根據(jù)老的state,和action生成新的state
function counter(state=0,action) {
    switch (action.type) {
        case '加機(jī)關(guān)槍':
            return state+1;
        case '減機(jī)關(guān)槍':
            return state-1;
        default:
            return 10;
    }
}

//新建store
const store = createStore(counter);

const init = store.getState();
console.log(init);

function listener() {
    const current = store.getState();
    console.log(`現(xiàn)在有機(jī)槍${current}把~`);
}
store.subscribe(listener);

//派發(fā)事件 傳遞action
store.dispatch({ type: '加機(jī)關(guān)槍' });
store.dispatch({ type: '加機(jī)關(guān)槍' });
store.dispatch({ type: '加機(jī)關(guān)槍' });
console.log(store.getState());

Redux如何與React一起使用?
把store.dispatch()方法傳遞給組件,內(nèi)部可以調(diào)用修改狀態(tài).
Subscribe訂閱render()函數(shù),每次修改都重新渲染.
Redux相關(guān)內(nèi)容,移到單獨(dú)的文件index.redux.js單獨(dú)管理.

更進(jìn)一步
處理異步
調(diào)試工具
更優(yōu)雅的和react結(jié)合.

redux處理異步,需要redux-thunk插件
Npm install redux-devtools-extension 并且開啟
使用react-redux優(yōu)雅的鏈接react和redux

安裝

$ cnpm install redux-thunk --save-dev

安裝完成后,需要applyMiddleware開啟thunk中間件
現(xiàn)在Action是返回對(duì)象,安裝這個(gè)插件以后可以返回函數(shù).使用dispatch提交action

怎么開啟applyMiddleware?
在index.js下

import { createStore , applyMiddleware} from 'redux';
import  thunk  from 'redux-thunk';

先創(chuàng)建store時(shí)候

const store = createStore(counter,applyMiddleware(thunk));

異步action


// 這個(gè)是異步函數(shù),一般是返回對(duì)象的,這里是返回的一個(gè)異步函數(shù). 因?yàn)榘惭b了redux-thunk插件
export function addGunAsync() {
    return dispatch=>{
        setTimeout(() => {
            dispatch(addGun())
        }, 2000);
    }
}

引用

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

注入

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

獲取屬性

    const addGunAsync = this.props.addGunAsync;
  render(){
    const store = this.props.store;
    const num = store.getState();
    const addGun = this.props.addGUN;
    const removeGun = this.props.removeGun; 
    const addGunAsync = this.props.addGunAsync;
    return (
      <div>
        <h1>現(xiàn)在有機(jī)槍{num}把!</h1>
        <Button onClick={() => store.dispatch(addGun())}>申請(qǐng)武器</Button>
        <Button onClick={() => store.dispatch(removeGun())}>上交武器</Button>
        <Button onClick={() => store.dispatch(addGunAsync())}>脫2天申請(qǐng)武器</Button>
      </div>
    )
  }

調(diào)試工具
在chrom下擴(kuò)展更多程序
在商店搜索 redux


image.png

重新開一個(gè)頁面,F12就會(huì)出現(xiàn)新擴(kuò)展的程序redux


image.png

如何使用:


image.png

第一步,引入compose

import { createStore , applyMiddleware, compose } from 'redux';

const store = createStore(counter, applyMiddleware(thunk));

改為

const store = createStore(counter,compose(
    applyMiddleware(thunk),
    window.devToolsExtension ? window.devToolsExtension():f=>f   //前提是安裝了Redux DevTools 
));

運(yùn)行界面:


image.png

老趙能力用起來很麻煩,為了方便管理.使用魏和尚來負(fù)責(zé)鏈接.
1.首先安裝插件

$: cnpm install react-redux --save-dev

2.忘記subscribe 記住reducer action dispatch即可.
3.React-redux提供Provider和connect2個(gè)接口來鏈接.

React-redux具體使用
Provider組件在應(yīng)用最外層,傳入store即可,只用一次.

更新代碼
在index.js

import { Provider } from 'react-redux';

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

render();

//狀態(tài)改變.就重新執(zhí)行以下render
store.subscribe(render);

注釋掉.

新增

ReactDOM.render(
    <Provider store={store}>
        <App  />
    </Provider>,
    document.getElementById('root')
);

Connect在組件內(nèi)部負(fù)責(zé)從外部獲取組件需要的參數(shù).
Connect可以用裝飾器的方式來寫.

在app.js

// export default App;
import  React  from "react";
import { Button } from 'antd-mobile';
import { addGun, removeGun, addGunAsync } from './index.redux';
import { connect } from 'react-redux';
class App extends React.Component {
  // constructor(props) {
  //   super(props);
  // }
  render(){
    //  const store = this.props.store;
    // const num = store.getState();
    const num = this.props.num;
    const addGun = this.props.addGun;
    const removeGun = this.props.removeGun; 
    const addGunAsync = this.props.addGunAsync;
    return (
      <div>
        <h1>現(xiàn)在有機(jī)槍{num}把!</h1>
        <Button onClick={addGun}>申請(qǐng)武器</Button>
        <Button onClick={removeGun}>上交武器</Button>
        <Button onClick={addGunAsync}>脫2天申請(qǐng)武器</Button>
      </div>
    )
  }
}

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

export default App;

Connect可以用裝飾器的方式來寫
但是需要一個(gè)插件(前提是create-react-app需要彈出個(gè)性化配置)
$ cnpm run eject 將它的配置彈出來
安裝插件

$ cnpm install babel-plugin-transform-decorators-legacy --save-dev

在package.json在給剛才安裝的插件配置上.

    "plugins": [
      [
        "import", 
        {
          "libraryName": "antd-mobile",
          "style": "css"
        }
      ],
      "transform-decorators-legacy"
    ]

由于有了Connect這個(gè)插件,
可以將


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

改為

@connect(state => ({num: state}),
  { addGun, removeGun, addGunAsync }
)

React后序?
什么數(shù)據(jù)應(yīng)該放在React里面
Redux管理ajax
Redux管理聊天數(shù)據(jù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容