国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

React+Koa全棧開發(fā)手記

wqj97 / 1633人閱讀

摘要:本項(xiàng)目中采用了進(jìn)行狀態(tài)管理,的主要作用是允許狀態(tài)在不同分支的組件中進(jìn)行傳遞,從而避免了使用原始方法如導(dǎo)致的不同分支組件之間數(shù)據(jù)無法傳遞子組件無法修改父組件狀態(tài)等問題。

項(xiàng)目功能

最近在做一個(gè)舊書交易網(wǎng)站,本屬于B/S體系結(jié)構(gòu)的課程作業(yè),但由于采用了新的框架所以躍躍欲試想都記錄下來。

實(shí)現(xiàn)一個(gè)舊書交易網(wǎng)站,基本功能如下:

實(shí)現(xiàn)用戶注冊(cè)、登錄功能,用戶注冊(cè)時(shí)需要填寫必要的信息并驗(yàn)證,如用戶名、密碼要求在6字節(jié)以上,email的格式驗(yàn)證,并保證用戶名和email在系統(tǒng)中唯一。

用戶登錄后可以發(fā)布要交易的書籍,需要編輯相關(guān)信息,包括書名、原價(jià)、出售價(jià)、類別和內(nèi)容介紹等信息、外觀照片等,可以通過ISBN和書名鏈接到外部系統(tǒng)(如Amazon/京東/當(dāng)當(dāng)?shù)染W(wǎng)站)的詳細(xì)介紹頁面。

根據(jù)用戶發(fā)布的書籍聚合生成首頁,可以分類檢索。

用戶可以設(shè)置交易模式為寄送還是線下交易,生成訂單時(shí)錄入不同內(nèi)容。

集成一個(gè)消息系統(tǒng),買家和賣家之間可以通信。

提供求購模塊,用戶可以發(fā)布自己想要的書籍。

界面樣式需要適配PC和手機(jī)的瀏覽器。

實(shí)現(xiàn)一個(gè)Android或iphone客戶端軟件,功能同網(wǎng)站,額外支持定位功能,發(fā)布時(shí)記錄位置,可以根據(jù)用戶的位置匹配最近的待售書籍。消息和訂單支持推送。

技術(shù)選型 數(shù)據(jù)庫

數(shù)據(jù)庫使用MySQL進(jìn)行開發(fā),因?yàn)榄h(huán)境之前都已經(jīng)配好了( ̄▽ ̄)"

后端

經(jīng)過Express和Koa比對(duì),最終選擇Koa作為基于Node.js的Web開發(fā)框架。Koa是一個(gè)新的web框架,由Express幕后原班人馬打造,語法上也使用了ES6新的語法(例如丟棄了回調(diào)函數(shù)而使用async解決異步調(diào)用問題),看起來十分優(yōu)雅o( ̄▽ ̄)o

前端

采用React+Semantic UI,由于之前對(duì)React有足夠多的實(shí)踐,因此本次重點(diǎn)還是放在后端開發(fā)及前后端連接上……

開發(fā)過程 參考教程

Vue+Koa全棧開發(fā)

Koa框架教程 - 阮一峰

Koa框架搭建 初始化

命令行輸入

npm init -y
npm i koa koa-json
npm i -D nodemon

更改package.json內(nèi)容,將scripts中的內(nèi)容更改為"start":"nodemon app.js"

根目錄下新建app.js

const Koa = require("koa");
const json = require("koa-json");
const logger = require("koa-logger");
const KoaRouter = require("koa-router");
const parser = require("koa-bodyparser");

const app = new Koa();
const router = new KoaRouter();

// Json Prettier Middleware
app.use(json());
app.use(parser());
app.use(logger());

// Simple Middleware Example
// app.use(async ctx => (ctx.body = { msg: "Hello world" }));

app.listen(4113, () => console.log("----------Server Started----------"));

module.exports = app;

命令行輸入node app.js,瀏覽器打開localhost:3000查看返回?cái)?shù)據(jù)

sequelize連接數(shù)據(jù)庫

安裝包

npm install sequelize-auto -g
npm install tedious -g
npm install mysql -g

進(jìn)入src目錄,輸入sequelize-auto -o "./schema" -d bookiezilla -h 127.0.0.1 -u root -p 3306 -x XXXXX -e mysql,(其中 -o 參數(shù)后面的是輸出的文件夾目錄, -d 參數(shù)后面的是數(shù)據(jù)庫名, -h 參數(shù)后面是數(shù)據(jù)庫地址, -u 參數(shù)后面是數(shù)據(jù)庫用戶名, -p 參數(shù)后面是端口號(hào), -x 參數(shù)后面是數(shù)據(jù)庫密碼 -e 參數(shù)后面指定數(shù)據(jù)庫為mysql)

此時(shí)schema文件夾下會(huì)自動(dòng)生成三個(gè)表的文件,例如:

/* jshint indent: 2 */

module.exports = function(sequelize, DataTypes) {
  return sequelize.define(
    "book",
    {
      BookID: {
        type: DataTypes.INTEGER(11),
        allowNull: false,
        primaryKey: true
      },
      BookName: {
        type: DataTypes.STRING(45),
        allowNull: true
      },
      BookCostPrice: {
        type: "DOUBLE",
        allowNull: true
      },
      BookSalePrice: {
        type: "DOUBLE",
        allowNull: true
      },
      BookCategory: {
        type: DataTypes.STRING(45),
        allowNull: true
      },
      BookPhoto: {
        type: DataTypes.STRING(45),
        allowNull: true
      },
      BookContent: {
        type: DataTypes.STRING(45),
        allowNull: true
      },
      BookISBN: {
        type: DataTypes.STRING(45),
        allowNull: true
      }
    },
    {
      tableName: "book"
    }
  );
};

serversrcconfig下新建文件database.js,用于初始化Sequelize和數(shù)據(jù)庫的連接。

const Sequelize = require("sequelize");

// 使用url連接的形式進(jìn)行連接,注意將root: 后面的XXXX改成自己數(shù)據(jù)庫的密碼
const BookieZilla = new Sequelize(
  "mysql://root:XXXXX@localhost/bookiezilla",
  {
    define: {
      timestamps: false// 取消Sequelzie自動(dòng)給數(shù)據(jù)表加入時(shí)間戳(createdAt以及updatedAt),否則進(jìn)行增刪改查操作時(shí)可能會(huì)報(bào)錯(cuò)
    }
  }
);

module.exports = {
  BookieZilla // 將BookieZilla暴露出接口方便Model調(diào)用
};

為方便之后根據(jù)用戶id查詢信息,可先在數(shù)據(jù)庫中隨意增加一條數(shù)據(jù)。

serversrcmodels下新建文件userModel.js,數(shù)據(jù)庫和表結(jié)構(gòu)文件連接起來。

const db = require("../config/database.js");
const userModel = "../schema/user.js";// 引入user的表結(jié)構(gòu)
const BookieZilla = db.BookieZilla;// 引入數(shù)據(jù)庫

const User = BookieZilla.import(userModel);// 用sequelize的import方法引入表結(jié)構(gòu),實(shí)例化了User。

const getUserById = async function(id) {
  const userInfo = await User.findOne({
    where: {
      UserID: id
    }
  });
  return userInfo;
};

module.exports = {
  getUserById,
  getUserByEmail
};

serversrccontrollers下新建文件userController.js,來執(zhí)行這個(gè)方法,并返回結(jié)果。

Koa 提供一個(gè) Context 對(duì)象,表示一次對(duì)話的上下文(包括 HTTP 請(qǐng)求和 HTTP 回復(fù))。通過加工這個(gè)對(duì)象,就可以控制返回給用戶的內(nèi)容。
const user = require("../models/userModel.js");

const getUserInfo = async function(ctx) {
  const id = ctx.params.id;// 獲取url里傳過來的參數(shù)里的id
  const result = await user.getUserById(id);
  ctx.body = result;// 將請(qǐng)求的結(jié)果放到response的body里返回
};

module.exports = {
  getUserInfo,
  vertifyUserLogin
};

serversrc outes下新建文件auth.js,用于規(guī)劃auth下的路由規(guī)則。

const auth = require("../controllers/userController.js");
const router = require("koa-router")();

router.get("/user/:id", auth.getUserInfo);

module.exports = router;

回到根目錄下的app.js,將這個(gè)路由規(guī)則“掛載”到Koa上去。

const Koa = require("koa");
const json = require("koa-json");
const logger = require("koa-logger");
const KoaRouter = require("koa-router");
const parser = require("koa-bodyparser");
const auth = require("./src/routes/auth.js");// 引入auth

const app = new Koa();
const router = new KoaRouter();

// Json Prettier Middleware
app.use(json());
app.use(parser());
app.use(logger());

// Simple Middleware Example
// app.use(async ctx => (ctx.body = { msg: "Hello world" }));

// Router Middleware
router.use("/auth", auth.routes());// 掛載到koa-router上,同時(shí)會(huì)讓所有的auth的請(qǐng)求路徑前面加上"/auth"的請(qǐng)求路徑。

app.use(router.routes()).use(router.allowedMethods());// 將路由規(guī)則掛載到Koa上。

app.listen(4113, () => console.log("----------Server Started----------"));

module.exports = app;

API Test

SUCCESS!!!

前后端數(shù)據(jù)傳遞

由于本項(xiàng)目采用的是前后端分離的架構(gòu),因此需要通過json來傳遞數(shù)據(jù),以實(shí)現(xiàn)登錄功能為例來闡述實(shí)現(xiàn)的具體步驟。

后端驗(yàn)證登錄

serversrcmodelsuserModel.js增加方法,用于通過郵箱查找用戶。

// ...
const getUserByEmail = async function(email) {
  const userInfo = await User.findOne({
    where: {
      UserEmail: email
    }
  });
  return userInfo;
};

module.exports = {
  getUserById,
  getUserByEmail
};

serversrccontrolleruserController.js增加方法,用于驗(yàn)證登錄信息并將結(jié)果以json形式返回給前端。

注意此處實(shí)際上應(yīng)用了JSON-WEB-TOKEN實(shí)現(xiàn)無狀態(tài)請(qǐng)求,關(guān)于jwt的原理和實(shí)現(xiàn)方法請(qǐng)參考這篇文章和這篇文章。

簡單來說,運(yùn)用了JSON-WEB-TOKEN的登錄系統(tǒng)應(yīng)該是這樣的:

用戶在登錄頁輸入賬號(hào)密碼,將賬號(hào)密碼(密碼進(jìn)行md5加密)發(fā)送請(qǐng)求給后端

后端驗(yàn)證一下用戶的賬號(hào)和密碼的信息,如果符合,就下發(fā)一個(gè)TOKEN返回給客戶端。如果不符合就不發(fā)送TOKEN回去,返回驗(yàn)證錯(cuò)誤信息。

如果登錄成功,客戶端將TOKEN用某種方式存下來(SessionStorage、LocalStorage),之后要請(qǐng)求其他資源的時(shí)候,在請(qǐng)求頭(Header)里帶上這個(gè)TOKEN進(jìn)行請(qǐng)求。

后端收到請(qǐng)求信息,先驗(yàn)證一下TOKEN是否有效,有效則下發(fā)請(qǐng)求的資源,無效則返回驗(yàn)證錯(cuò)誤。

使用前需要安裝相應(yīng)庫:

npm i koa-jwt jsonwebtoken util -s

此外,為保證安全性,后端數(shù)據(jù)庫的密碼不能采用明文保存,此處使用bcrypt的加密方式。

npm i bcryptjs -s
const user = require("../models/userModel.js");
const jwt = require("jsonwebtoken");
const bcrypt = require("bcryptjs");

const getUserInfo = async function(ctx) {
  const id = ctx.params.id;
  const result = await user.getUserById(id);
  ctx.body = result;
};

const vertifyUserLogin = async function(ctx) {
  const data = ctx.request.body; // post過來的數(shù)據(jù)存在request.body里
  const userInfo = await user.getUserByEmail(data.email);

  if (userInfo != null) { // 如果查無此用戶會(huì)返回null
    if (!bcrypt.compareSync(data.psw, userInfo.UserPsw) {
      ctx.body = {
        status: false,
        msg: "Wrong password"
      };
    } else { // 如果密碼正確
      const userToken = {
        id: userInfo.UserID,
        email: userInfo.UserEmail
      };
      const secret = "react-koa-bookiezilla"; // 指定密鑰,這是之后用來判斷token合法性的標(biāo)志
      const token = jwt.sign(userToken, secret); // 簽發(fā)token
      ctx.body = {
        status: true,
        token: token // 返回token
      };
    }
  } else {
    ctx.body = {
      status: false,
      msg: "User doesn"t exist"
    };
  }
};

module.exports = {
  getUserInfo,
  vertifyUserLogin
};

更新serversrc outesauth.js中的路由規(guī)則。

const auth = require("../controllers/userController.js");
const router = require("koa-router")();

router.get("/user/:id", auth.getUserInfo);
router.post("/login", auth.vertifyUserLogin);

module.exports = router;

前端校驗(yàn)數(shù)據(jù)并發(fā)送請(qǐng)求

前端主要使用了react-router進(jìn)行路由跳轉(zhuǎn),使用semantic-ui作為UI組件庫,使用axios發(fā)送請(qǐng)求,Login.js代碼如下:

import React, { Component } from "react";
import {
  Button,
  Form,
  Grid,
  Header,
  Image,
  Message,
  Segment,
  Loader
} from "semantic-ui-react";
import { NavLink, withRouter } from "react-router-dom";
import axios from "axios";
import Logo from "../images/logo.png";

class Login extends Component {
  state = {
    email: "",
    psw: "",
    alert: false,
    load: false
  };

  vertifyFormat = () => {
    var pattern = /^([A-Za-z0-9_-.])+@([A-Za-z0-9_-.])+.([A-Za-z]{2,4})$/;
    return pattern.test(this.state.email) && this.state.psw.length >= 6;
  };

  sendLoginRequest = () => {
    if (this.vertifyFormat()) {
      this.setState({
        alert: false,
        load: true
      });
      axios
        .post("/auth/login", {
          email: this.state.email,
          psw: this.state.psw
        })
        .then(res => {
          console.log(res);
        })
        .catch(err => {
          console.log(err);
        });
    } else {
      this.setState({
        alert: true
      });
    }
  };

  render() {
    var alert =
      this.state.alert === false ? (
        
) : ( ); var load = this.state.load === false ?
: ; return (
Log-in to your B::kzilla
{ this.setState({ email: event.target.value }); }} /> { this.setState({ psw: event.target.value }); }} /> {alert} {load}
New to us? Sign Up
); } } export default withRouter(Login);
React配置代理

安裝http-proxy-middleware中間件。

npm install http-proxy-middleware -s

create-react-app初始化的項(xiàng)目需要eject,使基本配置暴露出來。

npm run eject

clientsrc下新建文件setupProxy.js,配置代理轉(zhuǎn)發(fā)信息。

const proxy = require("http-proxy-middleware");

module.exports = function(app) {
  app.use(
    proxy("/api", {
      target: "http://localhost:4113",
      changeOrigin: true
    })
  );
  app.use(
    proxy("/auth", {
      target: "http://localhost:4113",
      changeOrigin: true
    })
  );
};

clientscriptsstart.js中進(jìn)行配置,在const devServer = new WebpackDevServer(compiler, serverConfig);后添加語句require("../src/setupProxy")(devServer);

發(fā)送請(qǐng)求格式如下:

axios
  .post("/auth/login", {
    email: this.state.email,
    psw: this.state.psw
  })
  .then(res => {
    console.log(res);
  })
  .catch(err => {
    console.log(err);
  });

喜聞樂見的測試環(huán)節(jié)!

設(shè)計(jì)原理 數(shù)據(jù)庫 User
*UserID UserName UserPsw *UserEmail
INT VARCHAR(45) VARCHAR(45) VARCHAR(45)
CREATE TABLE `bookiezilla`.`user` (
  `UserID` INT NOT NULL,
  `UserName` VARCHAR(45) NULL,
  `UserPsw` VARCHAR(45) NULL,
  `UserEmail` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`UserID`, `UserEmail`));
Book
*BookID BookName BookCostPrice BookSalePrice BookCategory BookPhoto BookContent BookISBN BookRefs
INT VARCHAR(45) DOUBLE DOUBLE VARCHAR(45) VARCHAR(45) VARCHAR(45) VARCHAR(45) VARCHAR(45)
CREATE TABLE `bookiezilla`.`book` (
  `BookID` INT NOT NULL,
  `BookName` VARCHAR(45) NULL,
  `BookCostPrice` DOUBLE NULL,
  `BookSalePrice` DOUBLE NULL,
  `BookCategory` VARCHAR(45) NULL,
  `BookPhoto` VARCHAR(45) NULL,
  `BookContent` VARCHAR(45) NULL,
  `BookISBN` VARCHAR(45) NULL,
  PRIMARY KEY (`BookID`));
Order
*OrderID *UserID *BookID TradeMethod TradeStatus TradeParty TraderID
INT INT INT VARCHAR(45) VARCHAR(45) VARCHAR(45) INT
CREATE TABLE `bookiezilla`.`order` (
  `OrderID` INT NOT NULL,
  `UserID` INT NOT NULL,
  `BookID` INT NOT NULL,
  `TradeMethod` VARCHAR(45) NULL,
  `TradeStatus` VARCHAR(45) NULL,
  `TraderID` INT NULL,
  PRIMARY KEY (`OrderID`));
前端 目錄結(jié)構(gòu)
.
│  .gitignore
│  package-lock.json
│  package.json
│  README.md
│  yarn.lock
│
├─config // 基本配置文件
│  │  env.js
│  │  modules.js
│  │  paths.js
│  │  pnpTs.js
│  │  webpack.config.js
│  │  webpackDevServer.config.js
│  │
│  └─jest
│          cssTransform.js
│          fileTransform.js
│
├─public
│      favicon.ico
│      index.html
│      manifest.json
│
├─scripts // eject后生成的文件配置
│      build.js
│      start.js
│      test.js
│
└─src // 主要頁面及組件部分
    │  App.css
    │  App.js
    │  index.css
    │  index.js
    │  serviceWorker.js
    │  setupProxy.js // 設(shè)置代理轉(zhuǎn)發(fā),解決跨域問題
    │
    ├─actions // react-redux需要定義的actions
    │      UpdateActions.js
    │
    ├─components // 頁面的組件部分
    │      BookList.jsx
    │      BookMarket.jsx
    │      FeedBack.jsx
    │      OrderInfo.jsx
    │      PublishForm.jsx
    │      SearchBar.jsx
    │      SideMenu.jsx
    │      StatisticData.jsx
    │      StepFlow.jsx
    │
    ├─images // 項(xiàng)目中使用的圖片資源
    │      logo.png
    │      matthew.png
    │
    ├─pages // 頁面部分
    │      Home.jsx
    │      Login.jsx
    │      Market.jsx
    │      Message.jsx
    │      Publish.jsx
    │      Signup.jsx
    │
    └─reducers // react-redux需要定義的reducers
            rootReducer.js    
實(shí)現(xiàn)細(xì)節(jié)
React-router

項(xiàng)目中使用了react-router來控制路由,基本原理如下:

App.js中引入路由對(duì)應(yīng)的頁面或組件,并引入react-router-dom中的BrowserRouterRouteSwitch組件進(jìn)行定義。

// App.jsx

import React, { Component } from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";

import SideMenu from "./components/SideMenu";
import Login from "./pages/Login";
import Signup from "./pages/Signup";
import Home from "./pages/Home";
import Market from "./pages/Market";
import Publish from "./pages/Publish";
import Message from "./pages/Message";
import OrderInfo from "./components/OrderInfo";

class App extends Component {
  render() {
    return (
      
        
{/* Only match one */}
); } } export default App;

當(dāng)項(xiàng)目頁面中需要進(jìn)行頁面跳轉(zhuǎn)時(shí),可使用react-router-dom中的withRouter將組件包裹起來,再使用NavLink進(jìn)行跳轉(zhuǎn)。

// Login.jsx

import { NavLink, withRouter } from "react-router-dom";

class Login extends Component {
  .....
  sendLoginRequest = () => {
    ......
    this.props.history.push("/home");
    render(){
       ......
    }
  };

export default withRouter(Login);

React-redux

本項(xiàng)目中采用了react-redux進(jìn)行狀態(tài)管理,redux的主要作用是允許狀態(tài)在不同分支的組件中進(jìn)行傳遞,從而避免了使用原始方法(如this.props)導(dǎo)致的不同分支組件之間數(shù)據(jù)無法傳遞、子組件無法修改父組件狀態(tài)等問題。具體使用方法如下:

src educers下新建文件rootReducer.js用于更新中心狀態(tài)樹中的信息。

// rootReducer.js

const initState = {
  id: null,
  token: null
};

const rootReducer = (state = initState, action) => {
  if (action.type === "UPDATE_ID") {
    return {
      ...state,
      id: action.id
    };
  }
  if (action.type === "UPDATE_TOKEN") {
    return {
      ...state,
      token: action.token
    };
  }
  return state;
};

export default rootReducer;

srcactions中新建文件UpdateActions.js用于定義行為。

// UpdateActions.js

export const updateId = id => {
  return {
    type: "UPDATE_ID",
    id: id
  };
};

export const updateToken = token => {
  return {
    type: "UPDATE_TOKEN",
    token: token
  };
};

srcindex.js中使用react-redux中的組件對(duì)項(xiàng)目入口文件進(jìn)行包裹,并在全局范圍內(nèi)建立狀態(tài)樹。

// index.js

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import "semantic-ui-css/semantic.min.css";
import { createStore } from "redux";
import { Provider } from "react-redux";
import rootReducer from "./reducers/rootReducer";

const store = createStore(rootReducer);

ReactDOM.render(
  
    ,
  ,
  document.getElementById("root")
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

當(dāng)需要更新狀態(tài)樹中的信息時(shí),使用引入的action作為函數(shù)進(jìn)行更新。

// Login.jsx

import { connect } from "react-redux";
import { updateId, updateToken } from "../actions/UpdateActions";

class Login extends Component {
  ......  
  sendLoginRequest = () => {
    ......
    this.props.updateId(res.data.id);
    this.props.updateToken(res.data.token);
    ......
  };  
}

const mapStateToProps = state => {
  return {};
};

const mapDispatchToProps = dispatch => {
  return {
    updateToken: token => {
      dispatch(updateToken(token));
    },
    updateId: id => {
      dispatch(updateId(id));
    }
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(withRouter(Login));

當(dāng)需要使用狀態(tài)樹中的信息時(shí),先調(diào)用react-redux中的connect包裹組件,再使用this.props直接調(diào)用即可。

// PublishForm.jsx

import { connect } from "react-redux";

class PublishForm extends Component {
    ......
    var UserID = this.props.id;
    var UserToken = this.props.token;
    ......
}
    
const mapStateToProps = state => {
  return {
    id: state.id,
    token: state.token
  };
};

export default connect(mapStateToProps)(PublishForm);

后端 目錄結(jié)構(gòu)
.
│  app.js
│  package-lock.json
│  package.json
│
└─src
    ├─config // 數(shù)據(jù)庫配置
    │      database.js
    │
    ├─controllers // 控制器,獲取請(qǐng)求數(shù)據(jù)并調(diào)用models中的方法進(jìn)行處理并返回結(jié)果
    │      apiController.js
    │      msgController.js
    │      userController.js
    │
    ├─models // 實(shí)例模型,主要使用Sequelize定義的方法對(duì)數(shù)據(jù)庫進(jìn)行增刪改查
    │      bookModel.js
    │      CommentModel.js
    │      orderModel.js
    │      userModel.js
    │
    ├─routes // 路由,不同文件對(duì)應(yīng)不同類型的api接口,分別與授權(quán)、功能實(shí)現(xiàn)、信息傳遞有關(guān)
    │      api.js
    │      auth.js
    │      msg.js
    │
    └─schema // 數(shù)據(jù)庫表結(jié)構(gòu),可使用Sequelize自動(dòng)生成
            book.js
            comment.js
            order.js
            user.js
實(shí)現(xiàn)細(xì)節(jié)
路由掛載

當(dāng)Koa后端監(jiān)聽的端口接收到請(qǐng)求時(shí),會(huì)根據(jù)app.js中的路由規(guī)則進(jìn)行處理,我們將不同類型的接口定義在不同文件中,再通過router.use()進(jìn)行調(diào)用,避免發(fā)生接口冗亂復(fù)雜的情況。

// app.js

const Koa = require("koa");
const json = require("koa-json");
const logger = require("koa-logger");
const KoaRouter = require("koa-router");
const parser = require("koa-bodyparser");
const auth = require("./src/routes/auth.js");
const api = require("./src/routes/api.js");
const msg = require("./src/routes/msg.js");

const app = new Koa();
const router = new KoaRouter();

// Json Prettier Middleware
app.use(json());
app.use(parser());
app.use(logger());

// Simple Middleware Example
// app.use(async ctx => (ctx.body = { msg: "Hello world" }));

// Router Middleware
router.use("/auth", auth.routes());
router.use("/msg", msg.routes());
router.use("/api", api.routes());

app.use(router.routes()).use(router.allowedMethods());

app.listen(4113, () => console.log("----------Server Started----------"));

module.exports = app;
// auth.js

const auth = require("../controllers/userController.js");
const router = require("koa-router")();

router.get("/user/:id", auth.getUserInfo);
router.post("/login", auth.vertifyUserLogin);
router.post("/signup", auth.signupNewUser);

module.exports = router;
// api.js

const api = require("../controllers/apiController.js");
const router = require("koa-router")();

router.get("/getbooks", api.getAllBooks);
router.get("/getorder/:id", api.getOrderInfo);
router.post("/searchbooks", api.searchBooks);
router.post("/publish", api.publishNewBook);
router.post("/confirmorder", api.updateOrderOfTrade);

module.exports = router;
// msg.js

const msg = require("../controllers/msgController.js");
const router = require("koa-router")();

router.get("/getcomments", msg.getAllComments);
router.post("/newcomment", msg.publishNewComment);

module.exports = router;
項(xiàng)目成果 登錄注冊(cè)

Bookizilla能夠?qū)崿F(xiàn)用戶注冊(cè)、用戶登錄功能,其中對(duì)用戶注冊(cè)時(shí)需要的數(shù)據(jù)做了格式處理(如驗(yàn)證Email格式、保證兩次密碼輸入數(shù)據(jù)相符且不小于6字節(jié)等)。如果用戶在注冊(cè)過程中出現(xiàn)錯(cuò)誤,則會(huì)出現(xiàn)相應(yīng)提示以指導(dǎo)用戶進(jìn)行正確輸入。

Login.jsx

Signup.jsx

個(gè)人主頁

Bookiezilla的主頁呈現(xiàn)的是與該用戶有關(guān)的信息數(shù)據(jù)(如FAVES、VIEWS等,但由于目前后端并未儲(chǔ)存相關(guān)數(shù)據(jù)所以暫用了mocks)及該用戶所發(fā)布的所有書籍。

Home.jsx

書籍市場

Bookiezilla的書籍市場呈現(xiàn)了所有用戶發(fā)布的所有書籍,用戶可以使用上方的搜索框輸入關(guān)鍵詞(如書名、標(biāo)簽 、ISBN等)。用戶還可點(diǎn)擊圖書下方按鈕以查看具體信息,進(jìn)而決定是否達(dá)成交易,也可點(diǎn)擊鏈接在Amazon中查看書籍的詳細(xì)介紹。

Market.jsx

書籍發(fā)布

Bookiezilla允許用戶發(fā)布書籍,并設(shè)置訂單的關(guān)鍵信息(如書籍基本信息、交易模式、尋求買家或賣家等)。需要注意的是,由于書籍發(fā)布和書籍求購很大一部分內(nèi)容是重合的,所以此處將二者合并并且給出TradeParty選項(xiàng)來使用戶選擇是想要發(fā)布書籍還是求購書籍。

Publish.jsx

信息發(fā)布

Bookiezilla設(shè)置了信息發(fā)布面板,用于用戶之間的溝通交流、信息發(fā)布等。用戶可直接發(fā)布評(píng)論或回復(fù)他人的評(píng)論,從而進(jìn)行持續(xù)性的交流。

Message.jsx

https://github.com/Sylvie-Hsu...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/106745.html

相關(guān)文章

  • 下一代基于Koa的NodeJS全棧開發(fā)框架

    Github上的腳手架實(shí)在太多,可能大多數(shù)都是只專注在前端的web開發(fā),例如流行的React生態(tài)中的create-react-app和Vue生態(tài)中的Vue-cli, 但是可能作為像我一樣的全棧開發(fā),一個(gè)只關(guān)注在前端開發(fā)的腳手架滿足不了所有的需求,我們可能需要開發(fā)更復(fù)雜的全棧JS的項(xiàng)目,所以這里介紹又一個(gè)基于NodeJS的全棧開發(fā)框架 koa-web-kit,不一定適合所有人,但至少又多了個(gè)選擇?。...

    oliverhuang 評(píng)論0 收藏0
  • 前端學(xué)習(xí)資源整理

    稍微整理了一下自己平時(shí)看到的前端學(xué)習(xí)資源,分享給大家。 html MDN:Mozilla開發(fā)者網(wǎng)絡(luò) SEO:前端開發(fā)中的SEO css 張鑫旭:張鑫旭的博客 css精靈圖:css精靈圖實(shí)踐 柵格系統(tǒng):詳解CSS中的柵格系統(tǒng) 媒體查詢:css媒體查詢用法 rem布局:手機(jī)端頁面自適應(yīng)布局 移動(dòng)前端開發(fā)之viewport的深入理解:深入理解viewport 淘寶前端布局:手機(jī)淘寶移動(dòng)端布局 fl...

    siberiawolf 評(píng)論0 收藏0
  • koa-cola:只需一個(gè)react組件,同時(shí)支持單頁應(yīng)用(SPA)和服務(wù)器渲染(SSR)

    摘要:是一個(gè)基于和的服務(wù)器端和瀏覽器端的的前后端全棧應(yīng)用框架。是的組件,并且會(huì)進(jìn)行數(shù)據(jù)初始化不但可以支持的數(shù)據(jù)初始化,還可以合并和的,使用同一個(gè),和的無縫結(jié)合。 koa-cola是一個(gè)基于koa和react的服務(wù)器端SSR(server side render)和瀏覽器端的SPA(single page application)的web前后端全棧應(yīng)用框架。 koa-cola使用typescr...

    XGBCCC 評(píng)論0 收藏0
  • 從項(xiàng)目中由淺入深的學(xué)習(xí)koa 、mongodb(4)

    摘要:序列文章從項(xiàng)目中由淺入深的學(xué)習(xí)微信小程序和快應(yīng)用從項(xiàng)目中由淺入深的學(xué)習(xí)從項(xiàng)目中由淺入深的學(xué)習(xí)前言的出現(xiàn)前端已經(jīng)可以用一把梭從前端寫到后臺(tái)。 showImg(https://segmentfault.com/img/bVbrRI5?w=1920&h=1080); 序列文章 從項(xiàng)目中由淺入深的學(xué)習(xí)vue,微信小程序和快應(yīng)用 (1)從項(xiàng)目中由淺入深的學(xué)習(xí)react (2)從項(xiàng)目中由淺入深的學(xué)...

    null1145 評(píng)論0 收藏0
  • 前端react+redux+koa寫的博客推薦

    摘要:搭建的博客曾經(jīng)用的寫的博客,現(xiàn)在看來已經(jīng)很了,所以用目前最火的框架重構(gòu)一下。后端重構(gòu)博客嘛,以前用寫的后臺(tái),所以略懂一些,作為一個(gè)前端開發(fā),目標(biāo)就是全棧嘛,選用了最為流行的也用了目前最為流行的作為后端配合。 React-Node搭建的博客 曾經(jīng)用的php+mysql+js寫的博客,現(xiàn)在看來已經(jīng)很low了,所以用目前最火的react+koa框架重構(gòu)一下。先上地址吧:目前線上版本http:...

    objc94 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<