express+mongodb+vue實(shí)現(xiàn)增刪改查-全棧之路

vue element mongodb express


效果圖

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

刪除數(shù)據(jù)

修改數(shù)據(jù)

查看詳情頁面

前言

最近一直想學(xué)下node,畢竟會node的前端更有市場。但是光看不練,感覺還是少了點(diǎn)什么,就去github上看別人寫的項(xiàng)目,收獲頗豐,于是準(zhǔn)備自己照葫蘆畫瓢寫一個。

作為程序員,一定要保持不斷學(xué)習(xí)的狀態(tài),這樣我們才可以在職場中有一席之位。

我相信現(xiàn)在出去面試,被問到的問題一定不限于html、css、javascript、jQuery了,層出不窮的框架(vue、angular、react),服務(wù)器語言(java、node),數(shù)據(jù)庫、ES6新特性等都會被提及。

如果你不清楚如何使用vue-cli快速快速創(chuàng)建一個項(xiàng)目骨架,可以去看我的這篇文章-手把手教你用vue-cli、webpack、vue-router、vue-resource構(gòu)建單頁應(yīng)用

如果此時你還停留在原地,止步不前的話。那么我敢斷言,你快被out了。

在深讀這篇文章之前,我想告訴你,讀完后,你可以有哪些收獲!

學(xué)習(xí)vue,你會知道除了jQuery這種結(jié)構(gòu)驅(qū)動(操作dom元素)外,還有更加便捷的數(shù)據(jù)驅(qū)動,媽媽再也不用擔(dān)心我忘記jQuery中那些可怕的選擇器了。
學(xué)習(xí)node,你會知道除了java、c、python這些陌生的后臺語言外,js既然也可以寫后臺,你可以定義自己的接口,不在依賴于那些后臺糙漢子。
學(xué)習(xí)mongodb,你會知道數(shù)據(jù)如何存儲在數(shù)據(jù)庫中,已經(jīng)如何進(jìn)行增刪改查。

說了這么多,我想你已經(jīng)知道了。對!沒錯,這將是你通向全棧的必經(jīng)之路。想想都興奮。那么接下來,讓我們進(jìn)入正文吧。

建議:可以去我的github上將我的代碼clone一份到本地,跟著我的思路捋一遍,相信看完,你一定會對自己更加有信心。代碼中會有詳細(xì)注釋,可以解除你的很多疑惑。如果讀完這篇文章,你有所收獲的話,不要忘記動動你那可愛的小手,給個star哦。


正文

文章中有許多細(xì)節(jié)地方,不會說的太細(xì),如果遇到檻的話,可以自行百度,遇到難以理解的地方,我會加以強(qiáng)調(diào)。

開發(fā)環(huán)境

本地需要安裝mongodb、nodejs、vue-cli(腳手架)

第一步:初始化項(xiàng)目

通過vue-cli腳手架,我們可以快速搭建一個項(xiàng)目骨架。

vue init webpack my-project

cd my-rpoject && npm install

cnpm run dev

如果在終端,你看到了下圖所示,表示項(xiàng)目已經(jīng)成功啟動。接著在瀏覽器地址欄中輸入localhost://8080,如果你看到了vue的歡迎界面,表示你已經(jīng)完成了第一步。

第一步:啟動項(xiàng)目

第二步:把本地的mongodb啟動起來

前提:下載mongodb,并且已經(jīng)配置好了環(huán)境變量。

如果覺得配置環(huán)境變量啥麻煩的話,可以用homebrew進(jìn)行一鍵安裝。

當(dāng)上述都o(jì)k的情況下,你只要進(jìn)入到mongodb的安裝目錄(比如我的mongodb安裝在/usr/local/bin/目錄下)執(zhí)行mongo命令,如果你看到下圖所示,表示你已經(jīng)完成了第二步。

第二步:啟動本地mongodb

第三步:把后臺接口寫好

提示:所謂的后臺接口,就是通過express建立路由,如果不明白的話可以去看下express介紹(這里放個鏈接)。

前提:通過npm安裝expressmongoose、body-parser模塊

express模塊用來創(chuàng)建路由
mongoose模塊用來創(chuàng)建數(shù)據(jù)庫,連接數(shù)據(jù)庫
body-parser模塊用來對post請求的請求體進(jìn)行解析

//通過命令行進(jìn)入項(xiàng)目,執(zhí)行以下命令安裝這三個模塊
cnpm install express body-parser mongoose --save

在項(xiàng)目根目錄建立個app.js文件,用來啟動express服務(wù)

//app.js文件

//1.引入express模塊
const express = require('express')
//2.創(chuàng)建app對象
const app = express()
//定義簡單路由
app.use('/',(req,res) => {
  res.send('Yo!')
})
//定義服務(wù)啟動端口
app.listen(3000,() => {
    console.log('app listening on port 3000.')
})

上述步驟走完后,在命令行執(zhí)行node app.js。通過瀏覽器訪問localhost:3000,頁面出現(xiàn)res.send()的內(nèi)容即表示成功。

第四步:創(chuàng)建數(shù)據(jù)模型

提示:所謂的數(shù)據(jù)模型,可以理解為你將來創(chuàng)建的表中,要存什么樣的數(shù)據(jù)片段,數(shù)據(jù)類型是什么。

在項(xiàng)目根目錄建立一個models文件夾,用來存儲數(shù)據(jù)模型,每個模型都是由一個Schema生產(chǎn),具體的我們不用太在意,如果有興趣可自行百度。

models文件夾中創(chuàng)建一個hero.js文件,內(nèi)容如下

//hero.js文件

//引入mongoose模塊
const mongoose = require('mongoose')

//定義數(shù)據(jù)模型,可以看到,我們下面創(chuàng)建了一個表,表中的數(shù)據(jù)有name、age、sex等字段,并且這些字段的數(shù)據(jù)類型也定義了,最后將model導(dǎo)出即可
const heroSchema = mongoose.Schema({
  name :String,
  age : String,
  sex : String,
  address : String,
  dowhat : String,
  imgArr:[],
  favourite:String,
  explain:String
}, { collection: 'myhero'})
//這里mongoose.Schema最好要寫上第二個參數(shù),明確指定到數(shù)據(jù)庫中的哪個表取數(shù)據(jù),我這里寫了myhreo,目的就是為了以后操作數(shù)據(jù)要去myhreo表中。
這里不寫第二個參數(shù)的話,后面你會遇到坑。

//導(dǎo)出model模塊
const Hero = module.exports = mongoose.model('hero',heroSchema);

第五步:建立CURD(增刪改查)路由接口

在項(xiàng)目根目錄創(chuàng)建一個router文件夾,文件夾中創(chuàng)建一個hero.js文件,內(nèi)容如下,分別為增刪改查、添加圖片等路由

//引入express模塊
const express = require("express");
//定義路由級中間件
const router = express.Router();
//引入數(shù)據(jù)模型模塊
const Hero = require("../models/hero");

// 查詢所有英雄信息路由
router.get("/hero", (req, res) => {
  Hero.find({})
    .sort({ update_at: -1 })
    .then(heros => {
      res.json(heros);
    })
    .catch(err => {
      console.log(2);
      res.json(err);
    });
});

// 通過ObjectId查詢單個英雄信息路由
router.get("/hero/:id", (req, res) => {
  Hero.findById(req.params.id)
    .then(hero => {
      res.json(hero);
    })
    .catch(err => {
      res.json(err);
    });
});

// 添加一個英雄信息路由
router.post("/hero", (req, res) => {
  //使用Hero model上的create方法儲存數(shù)據(jù)
  Hero.create(req.body, (err, hero) => {
    if (err) {
      res.json(err);
    } else {
      res.json(hero);
    }
  });
});

//更新一條英雄信息數(shù)據(jù)路由
router.put("/hero/:id", (req, res) => {
  Hero.findOneAndUpdate(
    { _id: req.params.id },
    {
      $set: {
        name: req.body.name,
        age: req.body.age,
        sex: req.body.sex,
        address: req.body.address,
        dowhat: req.body.dowhat,
        favourite: req.body.favourite,
        explain: req.body.explain
      }
    },
    {
      new: true
    }
  )
    .then(hero => res.json(hero))
    .catch(err => res.json(err));
});

// 添加圖片路由
router.put("/addpic/:id", (req, res) => {
  Hero.findOneAndUpdate(
    { _id: req.params.id },
    {
      $push: {
        imgArr: req.body.url
      }
    },
    {
      new: true
    }
  )
    .then(hero => res.json(hero))
    .catch(err => res.json(err));
});

//刪除一條英雄信息路由
router.delete("/hero/:id", (req, res) => {
  Hero.findOneAndRemove({
    _id: req.params.id
  })
    .then(hero => res.send(`${hero.title}刪除成功`))
    .catch(err => res.json(err));
});

module.exports = router;

最后將路由應(yīng)用到app.js(也就是在app.js文件中引入上述路由定義)

//app.js文件

......
//引入剛才定義的hero路由
const hero = require('./router/hero')
......
app.use('/api',hero)
......

這時你可以通過Postman(模擬http請求數(shù)據(jù)軟件)進(jìn)行查詢測試,如果可以查詢到數(shù)據(jù),代表后臺接口已經(jīng)成功寫好了

注意:在查詢之前,你要簡單學(xué)習(xí)下mongodb如何向數(shù)據(jù)庫中對應(yīng)的表里面任意添加一條數(shù)據(jù),否則,你查詢出來的數(shù)據(jù)為空?。?!

比如我上面創(chuàng)建了一個myhero表,那我在執(zhí)行上面查詢之前,我會往表中添加一條模擬數(shù)據(jù)

添加模擬數(shù)據(jù)
//db.myhero.insert意思就是向數(shù)據(jù)庫中表名為myhero的表中添加一條數(shù)據(jù)
db.myhero.insert({
    "imgArr" : [ 
        "http://ossweb-img.qq.com/images/lol/web201310/skin/big157000.jpg", 
        "http://ossweb-img.qq.com/images/lol/web201310/skin/big157001.jpg", 
        "http://ossweb-img.qq.com/images/lol/web201310/skin/big157002.jpg",    
    ],
    "name" : "亞索",
    "age" : "22",
    "sex" : "man",
    "address" : "德瑪西亞",
    "dowhat" : "中單、刺客",
    "favourite" : "死亡如風(fēng)常伴吾身",
    "explain" : "亞索是一個百折不屈的艾歐尼亞人,也是一名身手敏捷的劍客,能夠運(yùn)用風(fēng)的力量對抗敵人。年少輕狂的他曾為了榮譽(yù)而一再地?fù)p失珍貴的東西,他的職位、他的導(dǎo)師、最后是他的親兄弟。他因無法擺脫的嫌疑而身敗名裂,如今已是被人通緝的罪犯。亞索在家園的土地上流浪,尋找對過去的救贖。蒼茫間,只有疾風(fēng)指引著他的利劍。",
    })

這里進(jìn)行數(shù)據(jù)庫操作,可以在終端中進(jìn)行,也可以下載可視化工具Robo 3T(鏈接地址)進(jìn)行操作,會更加方便。


好了,到這里我們整個功能的復(fù)雜部分已經(jīng)實(shí)現(xiàn)。我們回顧下做了哪些準(zhǔn)備工作

  1. 通過vue-cli初始化項(xiàng)目
  2. 啟動本地mongodb服務(wù)
  3. 將后臺接口路由寫好app.js文件
  4. 創(chuàng)建我們存放數(shù)據(jù)的數(shù)據(jù)模型heroSchema.js文件
  5. 寫好增刪改查路由接口hero.js文件

一鼓作氣,接下來就是我們擅長的前端部分了?,F(xiàn)在的你可以稍微松口氣了。是不是覺得很刺激,很過癮~

第七步:選擇前端開發(fā)必要模塊

提示:這里可以自由發(fā)揮,我下載的模塊中有element、vue-resource。建議你跟我使用同樣的模塊,避免后期不必要麻煩,等你回過頭來對整個項(xiàng)目了然于心的時候,就可以隨心所欲的選擇你要用的技術(shù)了,

//element-ui是餓了么為我們前端開發(fā)者提供的組件化框架,拿來就可以用。好用到?jīng)]朋友。vue-resource是用來處理請求的,不過vue2.0后好像出現(xiàn)了個axios,不在維護(hù)vue-resource,不過我之前一直用vue-resource的,很方便,現(xiàn)在也可以用。
cnpm install element-ui vue-resource --save

第八步:建立首頁和詳情頁組件

src/components路徑下,建立兩個頁面,分別為List.vue(首頁)、Detail.vue(詳情頁)。

然后在src目錄下,建立一個router文件夾,文件夾中創(chuàng)建一個index.js前端路由文件

前端路由文件index.js文件內(nèi)容如下

//路由頁面

import Vue from 'vue'

//引入路由模塊,看下終端,如果終端提示vue-router模塊沒有安裝,安裝即可
import Router from 'vue-router'

//分別引入List、Detail兩個組件
import List from '@/components/List'
import Detail from '@/components/Detail'


Vue.use(Router)

//定義路由,這兩個路由會被映射到App.vue的<router-view></router-view>視口中
export default new Router({
  routes: [
    {
      path: '/',
      name: 'List',
      component: List
    },
    {
      path : '/league/:name',
      name : 'Detail',
      component : Detail
    },
  ]
})

第九步:處理跨域情況

因?yàn)槲覀兊?code>express服務(wù)是在localhost:3000端口啟動的,而我們的vue-cli創(chuàng)建的項(xiàng)目是在默認(rèn)端口8080啟動的,所以肯定會涉及到跨域的情況

好在vue-cli為我們提供了解決跨域的配置入口

找到根目錄中config目錄下面的index.js文件,里面有個配置項(xiàng)proxyTable,改寫這個配置項(xiàng)如下即可

處理跨域問題

這時,當(dāng)我們在前端用vue-resource訪問 /api 的時候,就會被代理到 http://localhost:3000/api,從而獲得需要的數(shù)據(jù)。說白了,也就是個轉(zhuǎn)換工作。

第十步:搭建頁面

到這里,所有準(zhǔn)備工作已經(jīng)完成,我們安心寫前端代碼即可。布局的話,就不多說了。交互方面主要就是在vue中的methods選項(xiàng)中定義一系列的方法,并且將方法通過@click="xxx"方法綁定到對應(yīng)的地方,具體方法定義看我寫的代碼即可。

完結(jié)

項(xiàng)目寫好后,就是打包了,并且將打包的dist文件夾作為express靜態(tài)文件服務(wù)的目錄。

cnpm run build
app.use(express.static('dist'))

最后看下整個項(xiàng)目的目錄結(jié)構(gòu)


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

歡迎小伙伴們提出自己的見解,并且指出文中的錯誤??
If this article has give you some help . why don't give me a star?!

傳送門:個人博客

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

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

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