【全栈之巅】Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台
本项目是 学习Bilibili 全栈之巅 视频教程相关源码和体会
https://gitee.com/blaunicorn/node-vue-wangzherongyao
持续更新中…
1.1 王者荣耀全栈开发部分截图
1.2 配置环境,下载安装 node 和MongoDB server 、 vscode
1.3 项目介绍:admin是后台界面部分、web是前台界面部分、server是前后台的后端接口部分。部署到服务器上,localhost:3000地址是前台首页不是后台的首页,添加admin才是后台的首页
// 全局安装vuecli,-g 全局安装
npm i -g @vue/cli
// 创建web页项目
vue create web
// 创建管理后端项目
vue create admin
// 新建server文件夹,并在其下
npm init -y
npm i -g nodemon
npm run serve //启动后台服务器
1.4 安装插件
// 全局安装nodemon
npm i -g nodemon
// admin端
vue add element
vue add router
npm install axios
// server端安装express@next版本 联接mongodb数据库 跨域 映射 上传文件中间件
npm i express@next mongoose cors inflection multer
1.5 server端自定义脚本中用nodemon运行代码
"serve": "nodemon index.js"
2.1 admin端创建分类及编辑页(admin/src/views/CategoryEdit.vue)
<template>
<div class="about">
//id 存在现实编辑,否则现实新建
<h1>{{id ? "编辑":"新建"}}分类</h1>
// 提交表单执行save方法
<el-form label-width="120px" @submit.native.prevent="save">
<el-form-item label="分类名称" >
<el-input v-model="model.name"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" native-type="submit">上传</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
props:{
id:{}
},
data(){
return{
model:{}
}
},
methods:{
async save(){
if(this.id){
this.$http.put(`/categories/${this.id}`,this.model)
}else{
this.$http.post('/categories',this.model)
}
this.$router.push('/categories/list')
this.$message({
type:'success',
message:'保存成功'
})
},
async fetch(){
const res = await this.$http.get(`/categories/${this.id}`)
this.model = res.data
}
},
created(){
this.id && this.fetch() // 判断是否通过router的props传回了id
}
}
</script>
2.1.1 admin 端请求接口放在http.js中(admin/src/http.js)
import axios from 'axios'
const http = axios.create({
baseURL:'http://localhost:3000/admin/api'
})
export default http
2.1.2 在Main.js中引用http.js(admin/src/main.js)
import http from './http'
Vue.prototype.$http = http
2.2 server端新建数据库、建立数据库模型、设置增删改查路由
// 后端连接数据库(server/plugins/db.js)
module.exports = app =>{
const mongoose = require('mongoose')
mongoose.connect('mongodb://127.0.0.1:27017/node-vue-moba',{
useNewUrlParser: true
})
}
// 创建表模板(server/models/Category.js)
const mongoose = require('mongoose')
const schema = new mongoose.Schema({
name:{type:String}
})
module.exports = mongoose.model('Category',schema)
// 写后端接口(server/route/admin/index.js)
module.exports = app =>{
const express = require('express')
const router = express.Router()
const Category = require('../../models/Category')
// 增
router.post('/categories',async(req,res)=>{
const model = await Category.create(req.body)
res.send(model)
})
// 改
router.put('/categories/:id',async(req,res)=>{
const model = await Category.findByIdAndUpdate(req.params.id,req.body)
res.send(model)
})
//删
router.delete('/categories/:id',async(req,res)=>{
const model = await Category.findByIdAndDelete(req.params.id,req.body)
res.send({
success: true
})
})
// 查
router.get('/categories',async(req,res)=>{
const items = await Category.find().limit(10)
res.send(items)
})
router.get('/categories/:id',async(req,res)=>{
const model = await Category.findById(req.params.id)
res.send(model)
})
app.use('/admin/api',router)
}
// 监听端口(server/index.js)
const express = require('express')
const app = express()
app.use(express.json())
app.use(require('cors')())
require('./plugins/db')(app)
require('./route/admin')(app)
app.listen(3000,()=>{
console.log('http://localhost:3000')
})
2.3 admin端定义vue-router路由
// admin端路由定义(admin/src/router/index.js)
const routes = [
{
path: '/',
name: 'Main',
component: () => import(/* webpackChunkName: "main" */ '../views/Main.vue'),
children: [
{
path: '/categories/create',
name: 'CategoriyEdit',
component: () => import('../views/CategoriyEdit.vue')
}
]
}
]
2.4 父类编辑 axios 传参、接收参数
// 后端server查(server\routes\admin\index.js)
router.get('/categories', async (req, res) => {
// console.log(req.query)
const limit = +req.query.limit || 10
const model = await Category.find().limit(limit)
res.send(model)
})
// 前端admin查询请求(admin\src\views\CategoriesList.vue)
async fetch() {
const params = {
limit: 10,
};
// 查询字符串传参 用 req.query接收 eg. http://localhost:9999/axios?id=1000 服务端 app.get('/axios', (req, res)
// restful风格URL 传参 用req.params.id 接收 eg.http://localhost:9999/axios/1000 服务端需要:id
const res = await this.$http.get('categories', { params });
console.log(res);
this.items = res.data;
},
2.5 父类删除 axios 传参、接收参数
// 前端admin删除具体物品请求(admin\src\views\CategoriesList.vue)
<template>
<div class="about">
<h1>分类列表</h1>
<el-table :data="items">
<el-table-column prop="_id" label="ID" width="230"> </el-table-column>
<el-table-column prop="parent.name" label="上级分类" width="120">
</el-table-column>
<el-table-column prop="name" label="分类名称" width="120">
</el-table-column>
<el-table-column fixed="right" label="操作" width="120">
<template slot-scope="scope">
<el-button
type="text"
size="small"
@click="$router.push(`/categories/edit/${scope.row._id}`)"
>编辑</el-button
>
<el-button @click="remove(scope.row)" type="text" size="small"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
...
async remove(row) {
console.log(row);
this.$confirm(`此操作将永久删除该分类${row.name}, 是否继续?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(async () => {
const res = await this.$http.delete(`/rest/categories/${row._id}`);
console.log(res);
this.$message({
type: 'success',
message: '删除成功!',
});
this.fetch();
})
.catch(() => {
this.$message({
type: 'info',
message: '已取消删除',
});
});
},
</script>