react_新手入門教程05——react + express + mongoose 實現CURD
上節用純前端的方式,實現CURD,
這節從之前的基礎上,做些修改,完成react 與後端介面的互動
注: 原本想用egg的:考慮大家用的express比較多,就換成express了
這節用到的的技術
- [x] promise
- [x] async await
- [x] mongodb
- [x] mongoose
- [x] mongoose-auto-increment
整個專案結構
├── models(mongoos.js model,宗旨上以資料表名一一對應)
├── routes(介面)
├── service (服務層,一般用於需要封裝的獨立服務,比如db)
├── src (前端工程)
│ |── src (前端原始碼)
│ |── components (公用自定義元件,以資料夾為單位)
│ |── img (圖片)
│ |── pages (頁面級別元件,以資料夾為單位)
│ |── service (前端的Ajax請求函式封裝)
│ |── style (核心樣式表-總)
│ |── tools (前端工具函式)
│ |── index.js (入口)
│ |── router.js (前端路由表)
│ |── README.md
├── app.js (入口)
├── README.md
後端
安裝expresss
此處省略。。。
mac下安裝mongodb
- brew install mongodb
- brew cask install launchrocket
- 開啟launchrocket start mongodb
安裝 mongoose
$ npm install mongoose
- 在後端service資料夾中新建db.js
- mongoose初始化
/**
* mongoose初始化配置
*/
const mongoose = require('mongoose'),
DB_URL = 'mongodb://localhost:27017/test',
autoIncrement = require('mongoose-auto-increment');
/**
* 連線
*/
const connection = mongoose.createConnection(DB_URL);
/**
* id自增外掛初始化
*/
autoIncrement.initialize(connection);
/**
* 連線成功
*/
mongoose.connection.on('connected', function () {
console.log('Mongoose connection open to ' + DB_URL);
});
/**
* 連線異常
*/
mongoose.connection.on('error',function (err) {
console.log('Mongoose connection error: ' + err);
});
/**
* 連線斷開
*/
mongoose.connection.on('disconnected', function () {
console.log('Mongoose connection disconnected');
});
module.exports = {
mongoose:mongoose,
connection:connection,
autoIncrement:autoIncrement,
};
- 後端modals資料夾中新建all.js
- 在all.js 定義 資料結構 及 運算元據庫的model
/**
* 定義 資料結構 及 運算元據庫的model
*/
const db = require('../service/db.js'),
Schema = db.mongoose.Schema;
/**
* 定義 modal資料結構
*/
const allSchema = new Schema({
name: {
type: String
}, //名字
age: {
type: String
}, //年齡
address: {
type: String
} //地址
}, {
versionKey: false // 版本號不顯示
})
//建立其他modal只需改下 model名 和 資料結構
const modalName = "all"
/**
* id自增外掛引入 設定從1開始自增
*/
allSchema.plugin(db.autoIncrement.plugin, { model: modalName, field: 'id', startAt:1 });
module.exports = db.connection.model(modalName, allSchema);
其中要提一點的是,mongodb本身無id自增功能,
所以應用了外掛 mongoose-auto-increment實現
之所以需要id自增,是因為後端主要通過id判斷來做增刪改查,
我比較習慣這樣,你也可以用其他方案 :)
關於mongoose的細節不贅述;
Mongoose介紹和入門:http://www.cnblogs.com/zhongweiv/p/mongoose.html
mongoose-auto-increment https://www.npmjs.com/package/mongoose-auto-increment
啟動後端
node app.js
增(create)刪(delete)改(update)查(select)
之前 前端做增刪改, 現在這塊邏輯放在後端
和之前的邏輯無差, 主要判斷物件中的id, status
若無id, 則新建
有id,status為0, 則修改
有id,status為-1,則刪除
//routes/all.js
//select
main.get('/list', async (request, response) => {
let ret = {
"success": true,
"code": 200,
"message": "",
"data": [],
}
const datas = await Model.find()
ret.data = datas
response.send(ret)
})
//create, delete, update
main.post('/update', async (request, response) => {
let ret = {
"success": true,
"code": 200,
"message": "",
"data": [],
}
const body = request.body,
id = body.id || 0,
status = body.status || 0
const args = body
if (!id) {
//新建
const dataSourceObj = await Model.create(args)
ret.data = {
id: dataSourceObj.id, create:true
}
}
else if (!status) {
//修改
const dataSourceObj = await Model.findOne({id: args.id})
for ( let key in args) {
if(key =='_id' || key =='id' ) {
continue
}
dataSourceObj[key]= args[key]
}
const new_dataSourceObj = await dataSourceObj.save()
ret.data = {
id: new_dataSourceObj.id, update:true
}
} else {
//刪除
const dataSourceObj = await Model.findOne({id: args.id})
const remove = await dataSourceObj.remove()
ret.data = {
id: dataSourceObj.id, delete:true
}
}
response.send(ret)
})
ok 這是介面邏輯,實際功能已經實現,
但未做介面防護,這點下節再寫吧
前端
前端在tools引入封裝的ajx工具
//src/tools/ajax.js
const joinQuery = function(params) {
var Querys = Object.keys(params).map( key => {
return `${key}=${params[key]}`
}).join('&')
return `?${Querys}`
}
//原生ajx
const ajax = function(request) {
var r = new XMLHttpRequest()
r.open(request.method, request.url, true)
if (request.contentType !== undefined) {
r.setRequestHeader('Content-Type', request.contentType)
}
r.onreadystatechange = function(event) {
if(r.readyState === 4) {
const data = JSON.parse(r.response)
request.success(data)
}
}
if (request.method === 'GET') {
r.send()
} else {
r.send(request.data)
}
}
//用Promise封裝原生ajx
const ajaxPromise = function(url, method, form) {
var p = new Promise((resolve, reject) => {
const request = {
url: url,
method: method,
contentType: 'application/json',
success: function(r) {
resolve(r)
},
error: function(e) {
const r = {
success: false,
message: '網路錯誤, 請重新嘗試',
}
//promise失敗扔出錯誤
reject(r)
},
}
if (method === 'post') {
const data = JSON.stringify(form)
request.data = data
}
ajax(request)
})
return p
}
//封裝 ajaxPromise
const _ajax = {
get: (path, params={}) => {
const url = path + joinQuery(params)
const method = 'get'
const form = {}
return ajaxPromise(url, method, form)
},
post: (path, params={})=>{
const url = path
const method = 'post'
return ajaxPromise(url, method, params)
},
}
module.exports = _ajax
在src/service中新建all元件的ajax請求,方便all元件呼叫
//src/service/all.js
import ajax from '../tools/ajax'
//元件請求類
const All = {
getList:(params) => {
let data = ajax.get('/all/list', params )
.then((response) => {
return response
})
return data
},
update: (params) => {
let data = ajax.post('/all/update', params )
.then((response) => {
return response
})
return data
}
}
export default All
後端安裝及介面邏輯和前端ajx工具都引入完成!
修改前端邏輯
之前的id是前端生成的
現在是後端提供,所以修改key為id
修改:
- key改為id
- saveData()方法刪除,新建和修改統一用updateDataHandle()方法
//src/pages/all/edit/index.js
class EditModel extends Component {
constructor(props) {
super(props);
this.state = {
— key:0,
}
}
onOk = () => {
const { editDataObj, updateDataHandle, onModelCancel, saveData} = this.props
//getFieldsValue() 獲取表單中輸入的值
const { getFieldsValue, resetFields } = this.props.form
const values = getFieldsValue()
//antd table需要加一個key欄位
//判斷是更新 還是新增
+ if(editDataObj.id) {
//輸入框本身無key
+ values.id = editDataObj.id
_ // //呼叫父元件方法改變dataSourse
_ // updateDataHandle(values)
}
_ // else {
_ // const key = this.state.key + 1
_ // this.setState({
_ // key:key,
_ // })
_ // values.key = key
_ // saveData(values)
_ // }
updateDataHandle(values)
//重置表單
resetFields()
onModelCancel()
}
//src/pages/all/index.js
- //儲存資料
- saveData = (updateData) => {
-
- const { dataSource } = this.state
- dataSource.push(updateData)
- this.setState({
- dataSource:dataSource,
- })
- }
//修改
updateDataHandle = async (values)=> {
- // const { dataSource } = this.state
- // const id = values.key,
- // status = values.status || 0
- //
- // const index = dataSource.findIndex(e=> e.key == id)
- // //替換
- // if(status >= 0) {
- // let replace = dataSource.splice(index,1,values)
- // } else {
- // //刪除
- // let removed = dataSource.splice(index,1)
- // }
+ const { data } = await AllService.update(values)
- // this.setState({
- // dataSource:data,
- // })
}
我們來新建一個資料試試
發現已經有http請求了,不過報錯了
這是http協議同源策略限制導致的,也就是俗稱的埠跨域
這裡 create-react-app 已經提過了一個簡單的方法
在src/package.json中加一句 "proxy": "http://localhost:8000"
{
"name": "public",
"version": "0.1.0",
"private": true,
"dependencies": {
"antd": "^3.2.2",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-router-dom": "^4.2.2",
"react-scripts": "1.1.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
+ "proxy": "http://localhost:8000"
}
配置完後,記得重啟下前端 yarn start
再新建一條資料可以看到, 新建成功
但資料並未渲染在table上, 所新增一個請求列表資料的方法
//src/pages/all/index.js
+ //請求列表資料
+ getDataSourseList = async () => {
+ const { data } = await AllService.getList()
+ this.setState({
+ dataSource:data,
+ })
+ }
//修改
updateDataHandle = async (values)=> {
const { data } = await AllService.update(values)
+ this.getDataSourseList()
}
資料新建資料就有了
現在還有個問題: 重新整理路由後,資料未渲染在table上
所以這裡需要加個reactd的鉤子:componentWillMount()
componentWillMount會在元件render之前執行
react生命週期:https://hulufei.gitbooks.io/react-tutorial/content/component-lifecycle.html
//src/pages/all/index.js
+//componentWillMount會在元件render之前執行
+ componentWillMount() {
+ this.getDataSourseList()
+ }
最後修復剩下的幾個bug
- fix: 刪除
- fix: id不顯示
//刪除
deleteHandle = (record) => {
confirm({
- title: `您確定要刪除?(${record.key})`,
+ title: `您確定要刪除?(${record.id})`,
onOk: () => {
this.updateDataHandle({
- key:record.key,
+ id:record.id,
status:-1,
})
},
});
}
render() {
// editVisiable控制彈窗顯示, dataSource為tabale渲染的資料
//
const { editVisiable, dataSource, editDataObj} = this.state
+ //資料加個key 喂antd
+ dataSource.map((e,index)=> e.key = index+1)
return (
<div className="content-inner">
<Button type ='primary' onClick={ this.addDataSource }> 新建資料</Button>
<Table
columns = {this.columns}
dataSource={dataSource}
/>
<EditModal
editVisiable={ editVisiable }
onModelCancel={ this.onModelCancel}
saveData = { this.saveData }
editDataObj = { editDataObj }
updateDataHandle = { this.updateDataHandle }
/>
</div>
);
}
//定義表格
columns = [{
title: 'id',
- dataIndex: 'key',
- key: 'key',
+ dataIndex: 'id',
+ key: 'id',
},{
title: '姓名',
dataIndex: 'name',
key: 'name',
}, {
title: '年齡',
dataIndex: 'age',
key: 'age',
}, {
title: '住址',
dataIndex: 'address',
key: 'address',
}, {
title: '操作',
dataIndex: 'operation',
key: 'operation',
render: (text, record) => (
<div style={{ textAlign: 'ceter' }}>
<a href="javascript:void(0)" style={{ marginRight: '10px' }}
onClick={() => this.editHandle(record)}
>編輯</a>
<a href="javascript:void(0)" style={{ marginRight: '10px' }}
onClick={() => this.deleteHandle(record)}
>刪除</a>
</div>
),
}];
github地址:https://github.com/hulubo/react-express-mongoose-CURD-demo
其中前端的包和後端的包應該放一起的,先這樣吧,到時候改
(完...)
相關文章
- React新手入門 教程React
- express+mongoose簡易登入,以及封裝思想(純新手向)ExpressGo封裝
- JDBC+MySQL入門實戰(實現CURD的例子)JDBCMySql
- 新手入門,webpack入門詳細教程Web
- Jwt的新手入門教程JWT
- 使用express+mongoose對mongodb實現增刪改查操作ExpressMongoDB
- MyBatis入門學習-連線oracle實現CURD基本操作MyBatisOracle
- React Hooks 入門教程ReactHook
- mongoose的入門使用Go
- Golang 新手教程:入門速成指南Golang
- Django新手圖文入門教程Django
- Mac新手的入門教程(一)Mac
- Apache Kafka教程--Kafka新手入門ApacheKafka
- 新手必看的iShowU Instant入門教程
- react-router4入門教程React
- Express快速入門Express
- [express+mongoose](增刪改查)ExpressGo
- SmartSql使用教程(2)—使用動態代理實現CURDSQL
- Modelsim模擬新手入門最詳細教程
- Express 新手概述Express
- Python語言如何入門?新手入門教程限時免費領Python
- Vue+Express實現登入,登出VueExpress
- React實戰入門指南React
- 新手搭建簡潔的Express-React-Redux腳手架ExpressReactRedux
- react-query手把手教程①-入門react-queryReact
- 用express+mongoose快速開發API介面ExpressGoAPI
- Mongoose在Express、Koa、 Egg中使用對比GoExpress
- React.js入門基礎與專案實戰開發視訊教程 React基礎教程ReactJS
- 新手入門必備:kylin安裝教程介紹!
- node+express+mysql入門ExpressMySql
- **Git新手入門**Git
- typer 新手入門
- 新手入門教程:如何將Evernote筆記本匯入到Outline筆記
- Latex排版學習筆記(2)——Latex新手入門教程筆記
- Python入門教程100天:Day05-練習總結Python
- 《MySQL 入門教程》第 05 篇 賬戶和許可權MySql
- MongoDB 新手入門 - AggregationMongoDB
- MongoDB 新手入門 - CRUDMongoDB