在本教程中,我们将使用MEVN栈建立一个小项目。MEVN是MongoDB、Express、VueJS和Node.js作为全栈应用程序的首字母缩写。MongoDB是我们的数据存储机制,Express是处理HTTP请求和路由的中间件,VueJS是渲染数据的客户端JavaScript,而Node.js是我们的应用程序将运行的服务器。作为额外的奖励,我们将包括一个很酷的Bootswatch主题,使CSS看起来不错。让我们开始吧。
创建目录并运行npm init
为了开始,我们将添加一个新的目录来存放我们的服务器代码,并运行npm init -y ,为我们初始化一个package.json文件。
node $mkdir MEVN-Tutorial
node $cd MEVN-Tutorial
MEVN-Tutorial $npm init -y
Wrote to C:nodeMEVN-Tutorialpackage.json:
{
"name": "MEVN-Tutorial", "version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
向项目添加依赖性
现在我们可以添加所有我们将在这个项目中使用的依赖项。我们将添加Express、Morgan、Cors和body-parser来开始。Express用于创建API,Morgan用于将http请求记录到控制台,cors允许客户端与前端对话,而body-parser则用于让后端读取从前端发送的数据。
MEVN-Tutorial $npm install express morgan cors body-parser
npm notice created a lockfile as package-lock.json. You should commit this file.npm WARN MEVN-Tutorial@1.0.0 No description
npm WARN MEVN-Tutorial@1.0.0 No repository field.
+ express@4.16.3
+ body-parser@1.18.3
+ morgan@1.9.0
+ cors@2.8.4
added 63 packages from 50 contributors and audited 161 packages in 4.205s
found 0 vulnerabilities
添加一个index.js文件
让我们为我们的项目添加一个index.js文件,因为这将是应用程序的入口。
MEVN-Tutorial $touch index.js

测试我们的服务器
我们已经准备好了一切,可以测试我们的服务器。我们只需要添加一点代码来使它工作。
index.js
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const app = express();
app.use(morgan('tiny'));
app.use(cors());
app.use(bodyParser.json());
app.get('/', (req, res) => {
res.json({
message: 'Behold The MEVN Stack!'
});
});
const port = process.env.PORT || 4000;
app.listen(port, () => {
console.log(`listening on ${port}`);
});
现在我们可以像这样运行该项目。
MEVN-Tutorial $node index.js
listening on 4000
如果我们在浏览器中加[载http://localhost:4000/,我们可以看到服务器正在工作。很好!

创建客户端 客户端目录
我们将在客户端使用Vue.js,所以现在让我们继续开始设置它。首先,我们要安装Vue Cli。
MEVN-Tutorial $npm i @vue/cli
一旦完成,让我们运行vue create client 命令,选择Router和Linter / Formatter选项。





当你完成了所有的提示后,你应该看到类似下面的东西。基本上,我们现在正在使用Vue cli在客户端文件夹中为我们的后端api构建前端。
✨ Creating project in C:nodeMEVN-Tutorialclient.
🗃 Initializing git repository...
⚙ Installing CLI plugins. This might take a while...
> yorkie@2.0.0 install C:nodeMEVN-Tutorialclientnode_modulesyorkie
> node bin/install.js
setting up Git hooks
done
added 1081 packages from 734 contributors and audited 10674 packages in 101.129sfound 0 vulnerabilities
🚀 Invoking generators...
📦 Installing additional dependencies...
added 109 packages from 43 contributors and audited 12463 packages in 41.475s
found 0 vulnerabilities
⚓ Running completion hooks...
📄 Generating README.md...
🎉 Successfully created project client.
👉 Get started with the following commands:
$ cd client
$ npm run serve
哇!Vue cli是非常酷的!好吧,既然它说我们可以运行这两个命令,我们就这么做,然后访[问http://localhost:8080/#/,看看我们的Vue安装是否运行。

现在,为了改变现状,我们将把Bootswatch Sketchy主题的CSS添加到index.html中,就像我们在这里看到的那样。

现在,当我们看我们的前端时,看看这个很酷的效果吧

好极了。我们现在有了一个可以使用API的前端,而我们还在构建这个API。事实上,让我们转回后端代码,继续构建所需的东西。
用Monk连接到MongoDB
在另一个教程中,我们使用Mongoose连接到我们的MongoDB服务器。在这一集,我们将使用Monk,它是一个更轻的软件包,可以快速使用。所以我们现在就安装Monk,同时我们也可以安装Joi来进行一些简单的数据验证。
MEVN-Tutorial $npm i monk joi
创建一个消息模型
就这样。我们已经准备好创建一个模型来存储用户可能提交给我们api的消息。在我们的项目中,我们可以添加一个db 目录,然后把connection.js 和messages.js 文件放在那里。
MEVN-Tutorial $mkdir db
MEVN-Tutorial $cd db
db $touch connection.jsdb $touch messages.js
connection**.js**
在connection.js文件中,我们可以添加这段代码,它将允许我们连接到MongoDB。
const monk = require('monk');
const connectionString = process.env.MONGODB_URI || 'localhost/mevnStack';
const db = monk(connectionString);
module.exports = db;
messages.js
这是用于处理消息的模型。
const Joi = require('joi');
const db = require('./connection');
const schema = Joi.object().keys({
username: Joi.string().alphanum().required(),
subject: Joi.string().required(),
message: Joi.string().max(500).required(),
imageURL: Joi.string().uri({
scheme: [
/https?/
]
})
});
const messages = db.get('messages');
function getAll() {
return messages.find();
}
function create(message) {
if (!message.username) message.username = 'Anonymous';
const result = Joi.validate(message, schema);
if (result.error == null) {
message.created = new Date();
return messages.insert(message);
} else {
return Promise.reject(result.error);
}
}
module.exports = {
create,
getAll
};
添加一个路由来从Mongodb获取消息
在index.js中,我们可以添加这段代码。
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const messages = require('./db/messages');
const app = express();
app.use(morgan('tiny'));
app.use(cors());
app.use(bodyParser.json());
app.get('/', (req, res) => {
res.json({
message: 'Behold The MEVN Stack!'
});
});
app.get('/messages', (req, res) => {
messages.getAll().then((messages) => {
res.json(messages);
});
});
const port = process.env.PORT || 4000;
app.listen(port, () => {
console.log(`listening on ${port}`);
});
我们现在甚至可以测试这个。在一个命令提示符中,我们可以运行mongod ,以启动我们的Mongo服务器。然后,我们需要运行node index.js 来启动我们的项目。在这一点上,如果我们访[问http://localhost:4000/messages,我们得到的是一个空数组。这其实是好事,因为这意味着我们正在与Mongo数据库对话,只是里面还没有任何消息。
添加一个路由来创建一个消息
在index.js中,让我们添加一个路由来处理对API的POST请求,这将向数据库中添加一个新的消息。
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const messages = require('./db/messages');
const app = express();
app.use(morgan('tiny'));
app.use(cors());
app.use(bodyParser.json());
app.get('/', (req, res) => {
res.json({
message: 'Behold The MEVN Stack!'
});
});
app.get('/messages', (req, res) => {
messages.getAll().then((messages) => {
res.json(messages);
});
});
app.post('/messages', (req, res) => {
console.log(req.body);
messages.create(req.body).then((message) => {
res.json(message);
}).catch((error) => {
res.status(500);
res.json(error);
});
});
const port = process.env.PORT || 4000;
app.listen(port, () => {
console.log(`listening on ${port}`);
});
使用Postman向API发送请求
我们现在可以做的是使用Postman向API发送一个POST请求。

现在让我们用Compass来看看数据是否在数据库中。看起来不错!

此外,如果我们访问http://localhost:4000/messages,我们现在看到存储在数据库中的消息以JSON格式返回。

消耗API并使用Vue显示消息
我们的API现在可以工作了。它能够接受并返回JSON格式的消息。现在我们想用我们的Vue客户端在屏幕上渲染一个或多个消息。我们可以先在Home.vue中添加以下Vue代码。
<template>
<div>
<hr>
<div class="list-unstyled" v-for="message in messages" :key="message._id">
<li class="media">
<img v-if="message.imageURL" class="mr-3" :src="message.imageURL" :alt="message.subject">
<div class="media-body">
<h4 class="mt-0 mb-1">{{message.username}}</h4>
<h5 class="mt-0 mb-1">{{message.subject}}</h5>
{{message.message}}
<br />
<small>{{message.created}}</small>
</div>
</li>
<hr>
</div>
</div>
</template>
<script>
const API_URL = "http://localhost:4000/messages";
export default {
name: "home",
data: () => ({
error: "",
messages: []
}),
mounted() {
fetch(API_URL)
.then(response => response.json())
.then(result => {
this.messages = result;
});
},
methods: {}
};
</script>
<style>
img {
max-width: 300px;
height: auto;
}
</style>
现在要测试这个,我们实际上需要节点实例的运行。在MEVN-Tutorial目录中,我们必须运行node index.js 来启动我们的API服务器。然后,我们还必须通过打开一个*不同的*命令提示符并从客户端目录中运行npm run serve ,来启动我们的客户端。希望这是有意义的。一旦完成,我们将有两个实例在运行。
http://localhost:4000/messages 将提供后端API。
http://localhost:8080/#/ 将提供我们的客户端服务。
好了,随着这两个实例的运行,我们的Home.vue文件被填充了一些Vue标记 - 我们可以看到我们的数据正在页面上呈现。很好!

这真是太酷了。我们的浏览器正在向Express服务器发出GET请求,然后它又以来自MongoDB数据库的JSON数据作为回应。在这一点上,我们的Vue.js代码消耗了这些JSON数据,并将其渲染到页面上。非常好!
添加一个Vue表单来提交新消息
现在我们可以把这段代码添加到Home.vue中,这样我们就有了一个添加新消息的表单。
<template>
<div>
<form @submit.prevent="addMessage" class="mb-3">
<div v-if="error" class="alert alert-dismissible alert-warning">
<button type="button" class="close" data-dismiss="alert">×</button>
<h4 class="alert-heading">Error!</h4>
<p class="mb-0">{{error}}</p>
</div>
<div class="form-group">
<label for="username">Username</label>
<input
v-model="message.username"
type="text"
class="form-control"
id="username" required>
</div>
<div class="form-group">
<label for="subject">Subject</label>
<input
v-model="message.subject"
type="text"
class="form-control"
id="subject"
placeholder="Enter a subject" required>
</div>
<div class="form-group">
<label for="message">Message</label>
<textarea
v-model="message.message"
class="form-control"
id="message"
rows="3"></textarea>
</div>
<div class="form-group">
<label for="imageURL">Image URL</label>
<input
v-model="message.imageURL"
type="url"
class="form-control"
id="imageURL"
placeholder="Enter URL to an image">
</div>
<button type="submit" class="btn btn-primary">Add Message</button>
</form>
<div class="list-unstyled" v-for="message in reversedMessages" :key="message._id">
<li class="media">
<img v-if="message.imageURL" class="mr-3" :src="message.imageURL" :alt="message.subject">
<div class="media-body">
<h4 class="mt-0 mb-1">{{message.username}}</h4>
<h5 class="mt-0 mb-1">{{message.subject}}</h5>
{{message.message}}
<br />
<small>{{message.created}}</small>
</div>
</li>
<hr>
</div>
</div>
</template>
<script>
const API_URL = "http://localhost:4000/messages";
export default {
name: "home",
data: () => ({
error: "",
messages: [],
message: {
username: "Enter a screen name",
subject: "",
message: "",
imageURL: ""
}
}),
computed: {
reversedMessages() {
return this.messages.slice().reverse();
}
},
mounted() {
fetch(API_URL)
.then(response => response.json())
.then(result => {
this.messages = result;
});
},
methods: {
addMessage() {
console.log(this.message);
fetch(API_URL, {
method: "POST",
body: JSON.stringify(this.message),
headers: {
"content-type": "application/json"
}
})
.then(response => response.json())
.then(result => {
if (result.details) {
// there was an error...
const error = result.details
.map(detail => detail.message)
.join(". ");
this.error = error;
} else {
this.error = "";
this.showMessageForm = false;
this.messages.push(result);
}
});
}
}
};
</script>
<style>
img {
max-width: 300px;
height: auto;
}
</style>
让我们继续前进,用一些新的数据来手动填写表单,测试一下。

一旦我们点击提交,POST请求就被发送到我们的API--连同我们在表单中输入的数据。现在我们在页面上看到了新的消息。很好!让我们再给信息添加一条信息。

让我们再添加一条信息,以确保事情正常进行。

再一次,我们在页面上看到了新的消息和我们之前添加的前两条消息。

Mongo Express Vue.js Node.js教程总结
本教程探讨了使用MEVN栈的基础知识,至此结束。当然,你可能听说过MEAN栈,它使用Mongo、Express、Angular和Node。这种方法将Angular从堆栈中移除,并在它的位置上插入Vue.js。有趣的是,这是最早的教程之一,在这个教程中,客户端只做了简单的与API的交互。Express、Mongo和Node合作提供了API,而Vue.js提供了客户端应用程序,通过该API发送和接收JSON数据。优秀的!