国产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è),但由于采用了新的框架所以躍躍欲試想都記錄下來。

</>復(fù)制代碼

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

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

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

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

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

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

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

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

  9. 實(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框架搭建 初始化

命令行輸入

</>復(fù)制代碼

  1. npm init -y
  2. npm i koa koa-json
  3. npm i -D nodemon

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

根目錄下新建app.js

</>復(fù)制代碼

  1. const Koa = require("koa");
  2. const json = require("koa-json");
  3. const logger = require("koa-logger");
  4. const KoaRouter = require("koa-router");
  5. const parser = require("koa-bodyparser");
  6. const app = new Koa();
  7. const router = new KoaRouter();
  8. // Json Prettier Middleware
  9. app.use(json());
  10. app.use(parser());
  11. app.use(logger());
  12. // Simple Middleware Example
  13. // app.use(async ctx => (ctx.body = { msg: "Hello world" }));
  14. app.listen(4113, () => console.log("----------Server Started----------"));
  15. module.exports = app;

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

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

安裝包

</>復(fù)制代碼

  1. npm install sequelize-auto -g
  2. npm install tedious -g
  3. 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è)表的文件,例如:

</>復(fù)制代碼

  1. /* jshint indent: 2 */
  2. module.exports = function(sequelize, DataTypes) {
  3. return sequelize.define(
  4. "book",
  5. {
  6. BookID: {
  7. type: DataTypes.INTEGER(11),
  8. allowNull: false,
  9. primaryKey: true
  10. },
  11. BookName: {
  12. type: DataTypes.STRING(45),
  13. allowNull: true
  14. },
  15. BookCostPrice: {
  16. type: "DOUBLE",
  17. allowNull: true
  18. },
  19. BookSalePrice: {
  20. type: "DOUBLE",
  21. allowNull: true
  22. },
  23. BookCategory: {
  24. type: DataTypes.STRING(45),
  25. allowNull: true
  26. },
  27. BookPhoto: {
  28. type: DataTypes.STRING(45),
  29. allowNull: true
  30. },
  31. BookContent: {
  32. type: DataTypes.STRING(45),
  33. allowNull: true
  34. },
  35. BookISBN: {
  36. type: DataTypes.STRING(45),
  37. allowNull: true
  38. }
  39. },
  40. {
  41. tableName: "book"
  42. }
  43. );
  44. };

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

</>復(fù)制代碼

  1. const Sequelize = require("sequelize");
  2. // 使用url連接的形式進(jìn)行連接,注意將root: 后面的XXXX改成自己數(shù)據(jù)庫的密碼
  3. const BookieZilla = new Sequelize(
  4. "mysql://root:XXXXX@localhost/bookiezilla",
  5. {
  6. define: {
  7. timestamps: false// 取消Sequelzie自動(dòng)給數(shù)據(jù)表加入時(shí)間戳(createdAt以及updatedAt),否則進(jìn)行增刪改查操作時(shí)可能會(huì)報(bào)錯(cuò)
  8. }
  9. }
  10. );
  11. module.exports = {
  12. BookieZilla // 將BookieZilla暴露出接口方便Model調(diào)用
  13. };

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

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

</>復(fù)制代碼

  1. const db = require("../config/database.js");
  2. const userModel = "../schema/user.js";// 引入user的表結(jié)構(gòu)
  3. const BookieZilla = db.BookieZilla;// 引入數(shù)據(jù)庫
  4. const User = BookieZilla.import(userModel);// 用sequelize的import方法引入表結(jié)構(gòu),實(shí)例化了User。
  5. const getUserById = async function(id) {
  6. const userInfo = await User.findOne({
  7. where: {
  8. UserID: id
  9. }
  10. });
  11. return userInfo;
  12. };
  13. module.exports = {
  14. getUserById,
  15. getUserByEmail
  16. };

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

</>復(fù)制代碼

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

</>復(fù)制代碼

  1. const user = require("../models/userModel.js");
  2. const getUserInfo = async function(ctx) {
  3. const id = ctx.params.id;// 獲取url里傳過來的參數(shù)里的id
  4. const result = await user.getUserById(id);
  5. ctx.body = result;// 將請(qǐng)求的結(jié)果放到response的body里返回
  6. };
  7. module.exports = {
  8. getUserInfo,
  9. vertifyUserLogin
  10. };

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

</>復(fù)制代碼

  1. const auth = require("../controllers/userController.js");
  2. const router = require("koa-router")();
  3. router.get("/user/:id", auth.getUserInfo);
  4. module.exports = router;

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

</>復(fù)制代碼

  1. const Koa = require("koa");
  2. const json = require("koa-json");
  3. const logger = require("koa-logger");
  4. const KoaRouter = require("koa-router");
  5. const parser = require("koa-bodyparser");
  6. const auth = require("./src/routes/auth.js");// 引入auth
  7. const app = new Koa();
  8. const router = new KoaRouter();
  9. // Json Prettier Middleware
  10. app.use(json());
  11. app.use(parser());
  12. app.use(logger());
  13. // Simple Middleware Example
  14. // app.use(async ctx => (ctx.body = { msg: "Hello world" }));
  15. // Router Middleware
  16. router.use("/auth", auth.routes());// 掛載到koa-router上,同時(shí)會(huì)讓所有的auth的請(qǐng)求路徑前面加上"/auth"的請(qǐng)求路徑。
  17. app.use(router.routes()).use(router.allowedMethods());// 將路由規(guī)則掛載到Koa上。
  18. app.listen(4113, () => console.log("----------Server Started----------"));
  19. 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增加方法,用于通過郵箱查找用戶。

</>復(fù)制代碼

  1. // ...
  2. const getUserByEmail = async function(email) {
  3. const userInfo = await User.findOne({
  4. where: {
  5. UserEmail: email
  6. }
  7. });
  8. return userInfo;
  9. };
  10. module.exports = {
  11. getUserById,
  12. getUserByEmail
  13. };

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)庫:

</>復(fù)制代碼

  1. npm i koa-jwt jsonwebtoken util -s

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

</>復(fù)制代碼

  1. npm i bcryptjs -s

</>復(fù)制代碼

  1. const user = require("../models/userModel.js");
  2. const jwt = require("jsonwebtoken");
  3. const bcrypt = require("bcryptjs");
  4. const getUserInfo = async function(ctx) {
  5. const id = ctx.params.id;
  6. const result = await user.getUserById(id);
  7. ctx.body = result;
  8. };
  9. const vertifyUserLogin = async function(ctx) {
  10. const data = ctx.request.body; // post過來的數(shù)據(jù)存在request.body里
  11. const userInfo = await user.getUserByEmail(data.email);
  12. if (userInfo != null) { // 如果查無此用戶會(huì)返回null
  13. if (!bcrypt.compareSync(data.psw, userInfo.UserPsw) {
  14. ctx.body = {
  15. status: false,
  16. msg: "Wrong password"
  17. };
  18. } else { // 如果密碼正確
  19. const userToken = {
  20. id: userInfo.UserID,
  21. email: userInfo.UserEmail
  22. };
  23. const secret = "react-koa-bookiezilla"; // 指定密鑰,這是之后用來判斷token合法性的標(biāo)志
  24. const token = jwt.sign(userToken, secret); // 簽發(fā)token
  25. ctx.body = {
  26. status: true,
  27. token: token // 返回token
  28. };
  29. }
  30. } else {
  31. ctx.body = {
  32. status: false,
  33. msg: "User doesn"t exist"
  34. };
  35. }
  36. };
  37. module.exports = {
  38. getUserInfo,
  39. vertifyUserLogin
  40. };

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

</>復(fù)制代碼

  1. const auth = require("../controllers/userController.js");
  2. const router = require("koa-router")();
  3. router.get("/user/:id", auth.getUserInfo);
  4. router.post("/login", auth.vertifyUserLogin);
  5. 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代碼如下:

</>復(fù)制代碼

  1. import React, { Component } from "react";
  2. import {
  3. Button,
  4. Form,
  5. Grid,
  6. Header,
  7. Image,
  8. Message,
  9. Segment,
  10. Loader
  11. } from "semantic-ui-react";
  12. import { NavLink, withRouter } from "react-router-dom";
  13. import axios from "axios";
  14. import Logo from "../images/logo.png";
  15. class Login extends Component {
  16. state = {
  17. email: "",
  18. psw: "",
  19. alert: false,
  20. load: false
  21. };
  22. vertifyFormat = () => {
  23. var pattern = /^([A-Za-z0-9_-.])+@([A-Za-z0-9_-.])+.([A-Za-z]{2,4})$/;
  24. return pattern.test(this.state.email) && this.state.psw.length >= 6;
  25. };
  26. sendLoginRequest = () => {
  27. if (this.vertifyFormat()) {
  28. this.setState({
  29. alert: false,
  30. load: true
  31. });
  32. axios
  33. .post("/auth/login", {
  34. email: this.state.email,
  35. psw: this.state.psw
  36. })
  37. .then(res => {
  38. console.log(res);
  39. })
  40. .catch(err => {
  41. console.log(err);
  42. });
  43. } else {
  44. this.setState({
  45. alert: true
  46. });
  47. }
  48. };
  49. render() {
  50. var alert =
  51. this.state.alert === false ? (
  52. ) : (
  53. );
  54. var load = this.state.load === false ?
    : ;
  55. return (
  56. Log-in to your B::kzilla
  57. {
  58. this.setState({
  59. email: event.target.value
  60. });
  61. }}
  62. />
  63. {
  64. this.setState({
  65. psw: event.target.value
  66. });
  67. }}
  68. />
  69. {alert}
  70. {load}
  71. Login
  72. New to us?
  73. Sign Up
  74. );
  75. }
  76. }
  77. export default withRouter(Login);
React配置代理

安裝http-proxy-middleware中間件。

</>復(fù)制代碼

  1. npm install http-proxy-middleware -s

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

</>復(fù)制代碼

  1. npm run eject

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

</>復(fù)制代碼

  1. const proxy = require("http-proxy-middleware");
  2. module.exports = function(app) {
  3. app.use(
  4. proxy("/api", {
  5. target: "http://localhost:4113",
  6. changeOrigin: true
  7. })
  8. );
  9. app.use(
  10. proxy("/auth", {
  11. target: "http://localhost:4113",
  12. changeOrigin: true
  13. })
  14. );
  15. };

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

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

</>復(fù)制代碼

  1. axios
  2. .post("/auth/login", {
  3. email: this.state.email,
  4. psw: this.state.psw
  5. })
  6. .then(res => {
  7. console.log(res);
  8. })
  9. .catch(err => {
  10. console.log(err);
  11. });

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

設(shè)計(jì)原理 數(shù)據(jù)庫 User
*UserID UserName UserPsw *UserEmail
INT VARCHAR(45) VARCHAR(45) VARCHAR(45)

</>復(fù)制代碼

  1. CREATE TABLE `bookiezilla`.`user` (
  2. `UserID` INT NOT NULL,
  3. `UserName` VARCHAR(45) NULL,
  4. `UserPsw` VARCHAR(45) NULL,
  5. `UserEmail` VARCHAR(45) NOT NULL,
  6. 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)

</>復(fù)制代碼

  1. CREATE TABLE `bookiezilla`.`book` (
  2. `BookID` INT NOT NULL,
  3. `BookName` VARCHAR(45) NULL,
  4. `BookCostPrice` DOUBLE NULL,
  5. `BookSalePrice` DOUBLE NULL,
  6. `BookCategory` VARCHAR(45) NULL,
  7. `BookPhoto` VARCHAR(45) NULL,
  8. `BookContent` VARCHAR(45) NULL,
  9. `BookISBN` VARCHAR(45) NULL,
  10. PRIMARY KEY (`BookID`));
Order
*OrderID *UserID *BookID TradeMethod TradeStatus TradeParty TraderID
INT INT INT VARCHAR(45) VARCHAR(45) VARCHAR(45) INT

</>復(fù)制代碼

  1. CREATE TABLE `bookiezilla`.`order` (
  2. `OrderID` INT NOT NULL,
  3. `UserID` INT NOT NULL,
  4. `BookID` INT NOT NULL,
  5. `TradeMethod` VARCHAR(45) NULL,
  6. `TradeStatus` VARCHAR(45) NULL,
  7. `TraderID` INT NULL,
  8. PRIMARY KEY (`OrderID`));
前端 目錄結(jié)構(gòu)

</>復(fù)制代碼

  1. .
  2. .gitignore
  3. │ package-lock.json
  4. package.json
  5. README.md
  6. │ yarn.lock
  7. ├─config // 基本配置文件
  8. │ │ env.js
  9. │ │ modules.js
  10. │ │ paths.js
  11. │ │ pnpTs.js
  12. │ │ webpack.config.js
  13. │ │ webpackDevServer.config.js
  14. │ │
  15. │ └─jest
  16. cssTransform.js
  17. fileTransform.js
  18. ├─public
  19. favicon.ico
  20. index.html
  21. manifest.json
  22. ├─scripts // eject后生成的文件配置
  23. build.js
  24. start.js
  25. test.js
  26. └─src // 主要頁面及組件部分
  27. App.css
  28. App.js
  29. index.css
  30. index.js
  31. serviceWorker.js
  32. │ setupProxy.js // 設(shè)置代理轉(zhuǎn)發(fā),解決跨域問題
  33. ├─actions // react-redux需要定義的actions
  34. UpdateActions.js
  35. ├─components // 頁面的組件部分
  36. BookList.jsx
  37. BookMarket.jsx
  38. FeedBack.jsx
  39. OrderInfo.jsx
  40. PublishForm.jsx
  41. SearchBar.jsx
  42. SideMenu.jsx
  43. StatisticData.jsx
  44. StepFlow.jsx
  45. ├─images // 項(xiàng)目中使用的圖片資源
  46. logo.png
  47. matthew.png
  48. ├─pages // 頁面部分
  49. Home.jsx
  50. Login.jsx
  51. Market.jsx
  52. Message.jsx
  53. Publish.jsx
  54. Signup.jsx
  55. └─reducers // react-redux需要定義的reducers
  56. rootReducer.js
實(shí)現(xiàn)細(xì)節(jié)
React-router

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

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

</>復(fù)制代碼

  1. // App.jsx
  2. import React, { Component } from "react";
  3. import { BrowserRouter, Route, Switch } from "react-router-dom";
  4. import SideMenu from "./components/SideMenu";
  5. import Login from "./pages/Login";
  6. import Signup from "./pages/Signup";
  7. import Home from "./pages/Home";
  8. import Market from "./pages/Market";
  9. import Publish from "./pages/Publish";
  10. import Message from "./pages/Message";
  11. import OrderInfo from "./components/OrderInfo";
  12. class App extends Component {
  13. render() {
  14. return (
  15. {/* Only match one */}
  16. );
  17. }
  18. }
  19. export default App;

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

</>復(fù)制代碼

  1. // Login.jsx
  2. import { NavLink, withRouter } from "react-router-dom";
  3. class Login extends Component {
  4. .....
  5. sendLoginRequest = () => {
  6. ......
  7. this.props.history.push("/home");
  8. render(){
  9. ......
  10. }
  11. };
  12. 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)樹中的信息。

</>復(fù)制代碼

  1. // rootReducer.js
  2. const initState = {
  3. id: null,
  4. token: null
  5. };
  6. const rootReducer = (state = initState, action) => {
  7. if (action.type === "UPDATE_ID") {
  8. return {
  9. ...state,
  10. id: action.id
  11. };
  12. }
  13. if (action.type === "UPDATE_TOKEN") {
  14. return {
  15. ...state,
  16. token: action.token
  17. };
  18. }
  19. return state;
  20. };
  21. export default rootReducer;

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

</>復(fù)制代碼

  1. // UpdateActions.js
  2. export const updateId = id => {
  3. return {
  4. type: "UPDATE_ID",
  5. id: id
  6. };
  7. };
  8. export const updateToken = token => {
  9. return {
  10. type: "UPDATE_TOKEN",
  11. token: token
  12. };
  13. };

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

</>復(fù)制代碼

  1. // index.js
  2. import React from "react";
  3. import ReactDOM from "react-dom";
  4. import "./index.css";
  5. import App from "./App";
  6. import * as serviceWorker from "./serviceWorker";
  7. import "semantic-ui-css/semantic.min.css";
  8. import { createStore } from "redux";
  9. import { Provider } from "react-redux";
  10. import rootReducer from "./reducers/rootReducer";
  11. const store = createStore(rootReducer);
  12. ReactDOM.render(
  13. ,
  14. ,
  15. document.getElementById("root")
  16. );
  17. // If you want your app to work offline and load faster, you can change
  18. // unregister() to register() below. Note this comes with some pitfalls.
  19. // Learn more about service workers: https://bit.ly/CRA-PWA
  20. serviceWorker.unregister();

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

</>復(fù)制代碼

  1. // Login.jsx
  2. import { connect } from "react-redux";
  3. import { updateId, updateToken } from "../actions/UpdateActions";
  4. class Login extends Component {
  5. ......
  6. sendLoginRequest = () => {
  7. ......
  8. this.props.updateId(res.data.id);
  9. this.props.updateToken(res.data.token);
  10. ......
  11. };
  12. }
  13. const mapStateToProps = state => {
  14. return {};
  15. };
  16. const mapDispatchToProps = dispatch => {
  17. return {
  18. updateToken: token => {
  19. dispatch(updateToken(token));
  20. },
  21. updateId: id => {
  22. dispatch(updateId(id));
  23. }
  24. };
  25. };
  26. export default connect(
  27. mapStateToProps,
  28. mapDispatchToProps
  29. )(withRouter(Login));

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

</>復(fù)制代碼

  1. // PublishForm.jsx
  2. import { connect } from "react-redux";
  3. class PublishForm extends Component {
  4. ......
  5. var UserID = this.props.id;
  6. var UserToken = this.props.token;
  7. ......
  8. }
  9. const mapStateToProps = state => {
  10. return {
  11. id: state.id,
  12. token: state.token
  13. };
  14. };
  15. export default connect(mapStateToProps)(PublishForm);

后端 目錄結(jié)構(gòu)

</>復(fù)制代碼

  1. .
  2. app.js
  3. │ package-lock.json
  4. package.json
  5. └─src
  6. ├─config // 數(shù)據(jù)庫配置
  7. database.js
  8. ├─controllers // 控制器,獲取請(qǐng)求數(shù)據(jù)并調(diào)用models中的方法進(jìn)行處理并返回結(jié)果
  9. apiController.js
  10. msgController.js
  11. userController.js
  12. ├─models // 實(shí)例模型,主要使用Sequelize定義的方法對(duì)數(shù)據(jù)庫進(jìn)行增刪改查
  13. bookModel.js
  14. CommentModel.js
  15. orderModel.js
  16. userModel.js
  17. ├─routes // 路由,不同文件對(duì)應(yīng)不同類型的api接口,分別與授權(quán)、功能實(shí)現(xiàn)、信息傳遞有關(guān)
  18. api.js
  19. auth.js
  20. msg.js
  21. └─schema // 數(shù)據(jù)庫表結(jié)構(gòu),可使用Sequelize自動(dòng)生成
  22. book.js
  23. comment.js
  24. order.js
  25. 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ù)雜的情況。

</>復(fù)制代碼

  1. // app.js
  2. const Koa = require("koa");
  3. const json = require("koa-json");
  4. const logger = require("koa-logger");
  5. const KoaRouter = require("koa-router");
  6. const parser = require("koa-bodyparser");
  7. const auth = require("./src/routes/auth.js");
  8. const api = require("./src/routes/api.js");
  9. const msg = require("./src/routes/msg.js");
  10. const app = new Koa();
  11. const router = new KoaRouter();
  12. // Json Prettier Middleware
  13. app.use(json());
  14. app.use(parser());
  15. app.use(logger());
  16. // Simple Middleware Example
  17. // app.use(async ctx => (ctx.body = { msg: "Hello world" }));
  18. // Router Middleware
  19. router.use("/auth", auth.routes());
  20. router.use("/msg", msg.routes());
  21. router.use("/api", api.routes());
  22. app.use(router.routes()).use(router.allowedMethods());
  23. app.listen(4113, () => console.log("----------Server Started----------"));
  24. module.exports = app;

</>復(fù)制代碼

  1. // auth.js
  2. const auth = require("../controllers/userController.js");
  3. const router = require("koa-router")();
  4. router.get("/user/:id", auth.getUserInfo);
  5. router.post("/login", auth.vertifyUserLogin);
  6. router.post("/signup", auth.signupNewUser);
  7. module.exports = router;

</>復(fù)制代碼

  1. // api.js
  2. const api = require("../controllers/apiController.js");
  3. const router = require("koa-router")();
  4. router.get("/getbooks", api.getAllBooks);
  5. router.get("/getorder/:id", api.getOrderInfo);
  6. router.post("/searchbooks", api.searchBooks);
  7. router.post("/publish", api.publishNewBook);
  8. router.post("/confirmorder", api.updateOrderOfTrade);
  9. module.exports = router;

</>復(fù)制代碼

  1. // msg.js
  2. const msg = require("../controllers/msgController.js");
  3. const router = require("koa-router")();
  4. router.get("/getcomments", msg.getAllComments);
  5. router.post("/newcomment", msg.publishNewComment);
  6. 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://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元查看
<