vue+node+mongodb实现的简单TodoList

login
主界面
主界面

起因

初学node,js既然也可以写后台,也可以自定义接口,身为一个小前端就一直就想利用node来做一个简单的后端。由此有了这个简单的demo,看官见笑。

项目搭建

环境需求vue-cli(脚手架)、mongodb、nodejs

mongodb中 数据库 -》集合-》文档文档的数据结构和JSON基本一样。所有存储在集合中的数据都是 BSON 格式。BSON 是一种类似 JSON 的二进制形式的存储格式,是 Binary JSON 的简称。
所以我们可以将mongodb想象成一个大json对象处理,传统的数据库中表和表之间的外键关联都不存在了.取而代之的是json格式的类树形结构.这就是转到mongodb之后最大的区别. 设计时把复杂的东西抽象成一个树形结构,而不是像从前那样先抽象成一个个实体,然后再抽象实体之间的关系,对前端而言mongodb做设计比sql做设计要简单很多

  1. 利用vue-cli初始化项目vue create todo_list

  2. 通过brew 安装mongodb

    使用 OSX 的 brew 来安装 mongodb的命令如下:
    
    sudo brew install mongodb
    要安装支持 TLS/SSL 命令如下:
    
    sudo brew install mongodb --with-openssl
    如果要安装开发版本,可以使用下面的命令:
    
    sudo brew install mongodb --devel
    然后,使用命令mongod --version来查看mongo DB是否安装成功。
    

    后由于mongodb已经不开源头
    我在这里直接安装默认的社区版本,执行brew install mongodb-community 也可以参考文档安装指定的版本;
    之后采用show dbs 查看安装是否成功

  • 如果发现数据库链接不上,可以在~/.bashrc中配置 export PATH=/usr/local/Cellar/mongodb-community/4.2.3/bin:${PATH}

  • 之后执行brew services start mongodb-community 最后进行mongo连接

    mongo链接

这里推荐使用robo3t这个mongodb可视化工具来快速的构建字典表

robo3T

前端项目结构

todolist
|
└─── NodeApi 后端api提供文件
│     |--controller  控制层,对数据库进行操作
|     |--db          数据库实例
|     |--middlewares node中间件
|     |--router      向前端暴露的接口
|     |--app         入口js
|     |--config      全局配置
|
└─── src 前端项目目录
│     |--api           前端请求接口
|     |--assets        图片相关
|     |--components    项目公关组件
|     |--router        路由
|     |--views         视图层
|  

前端主要的界面和设计就不细说,有兴趣的可以去github上看一下交互细节和页面逻辑。github地址

编写Node项目

通过npm安装koa、mongoose、body-parser模块

npm install koa body-parser mongoose --save
  • 数据库链接app.js
const Koa = require('koa');
const mongoose = require('mongoose');
const app = new Koa();

mongoose.connect('mongodb://localhost/todolist', 
{ useNewUrlParser: true }, err => {
  if (err) {
    console.error('Failed to connect to database');
  } else {
    console.log('数据库链接成功');
  }
});

app.listen(3000);

通过运行node app.js过浏览器访问localhost:3000就可以看到数据库已经链接

数据模型的构建

数据模型就是在数据库构建的表中,所需要的数据和数据的对应类型。

在项目根目录建立一个db文件夹,每个模型都是由一个Schema生产,举个例子在db文件夹中创建一个user.js文件,内容如下

//  name: {例子
//      type: String,
//      required: true, // 表示该字段是必需的
//      unique: true // 表示该字段唯一
//  },

//引入mongoose模块
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const userSchema = new Schema({
  user_id: { //用户id
    type: String
  },
  user_name: {  //用户名称
    type: String,
    required: true
  },
  user_password: {  //用户密码
    type: String,
    required: true
  },
  user_event: {
    type: Array,
    default: ['001'] //可以给与默认值
    // 字符串数组类型
  }
}, {
//这里mongoose.Schema最好要写上第二个参数
//明确指定到数据库中的哪个表取数据,我这里写了user,目的就是为了以后操作数据要去user表中。
  timestamps: { createdAt: 'created', updatedAt: 'updated' },
  collection: 'user',
  versionKey: false // 不需要 __v 字段,默认是加上的
})

//导出model模块
module.exports = mongoose.model('user', userSchema)

建立路由接口

在项目根目录创建一个router文件夹,文件夹中创建一个user_router.js文件,内容如下,分别为对用户的增删改查路由。项目模块较多,对应的路由也很多。如果一个个的去注册,效率太低。这里用node的fs模块去遍历读取routes下的所有路由文件,统一注册,可以直接在index.js中对所有的router进行引用。

//index.js
const fs = require('fs') //引入fs读取文件
module.exports = app => {
  fs.readdirSync(__dirname).forEach(file => {
    if (file === 'index.js' || file === '.DS_Store') {
      return
    }
    const route = require(`./${file}`)
    app.use(route.routes()).use(route.allowedMethods())//统一注册路由
  })
}

//user_controller.js
// 引入路由模块并实例化
const Router = require('koa-router') //引入koa路由实例
// const router = new Router();
const router = new Router({ prefix: '/user' }) //设置路由访问路径
// 导如对应的控制器
const user_controller = require('../controller/user_controller')

// 为控制器的方法定义请求路径和请求方式
router.post('/set', user_controller.set_User) //保存用户
router.post('/get', user_controller.get_User) //查询用户

module.exports = router

建立controller来控制事务(增删改查)

增删改查示例:

const User_col = require('../db/user')

5ca3894ee78a732a245e3bb8为id
//查询所有数据
User_col.find(function (err, ret) {}

//根据条件查询数据
User_col.find({
  _id: '5ca3894ee78a732a245e3bb8',
  username: 'czk'
}, function (err, ret) {}

//根据条件查询数据的第一个
User_col.findOne({})
//根据id值查询数据
User_col.findById('5ca3894ee78a732a245e3bb8', function (err, ret) {})

改 更新
User_col.findByIdAndUpdate('5ca3894ee78a732a245e3bb8', {})

删
User_col.findByIdAndDelete('5ca3894ee78a732a245e3bb8', function (err, ret) {})

增
let admin = {
  username: 'czk',
  password: '123',
}
User_col.create(admin)

在项目根目录建立一个controller文件夹,在controller文件夹中创建一个user_controller.js文件,内容如下

// 引入刚才定义的表
const User_col = require('../db/user')

// get 请求返回所有数据
const get_User = async (ctx, next) => {
  const result = await User_col.find({})
  ctx.status = 200
  ctx.body = {
    data: result
  }
}

// post 带一个 msg 参数,并插入数据库
const set_User = async (ctx, next) => {
  const req = ctx.request.body
  ctx.status = 200

  ctx.verifyParams({
    user_name: { type: 'string', required: true },
    //如果required为true则入参为必填项
    user_password: { type: 'string', required: true }
  })
  const result = await User_col.create(
  { user_name: req.user_name, user_password: req.user_password })
  // const result = await User_col.create({ req });
  ctx.body = {
    data: result
  }
}

// 暴露出这两个方法,在路由中使用
module.exports = {
  set_User,
  get_User
}

入口文件的构建

项目根目录的app.js,是后端项目的入口文件,内容如下

const Koa = require('koa')
const mongoose = require('mongoose')
const parameter = require('koa-parameter') // 参数校验
const error = require('koa-json-error') // 错误抓取
const cors = require('koa2-cors') //koa前端跨域,解决option跨域
const BodyParser = require('koa-bodyparser') // 获取json数据
const routing = require('./router/index') 
const config = require('./config')
const app = new Koa()

mongoose.connect('mongodb://localhost/todolist', 
{ useNewUrlParser: true }, err => {
  if (err) {
    console.error('Failed to connect to database')
  } else {
    console.log('数据库链接成功')
  }
})

app.use(cors()) 
app.use(BodyParser()) // 使用koa-bodyparser:
app.use(parameter(app)) // 参数校验

routing(app) // 路由处理
app.use(error({
  postFormat: (e, { stack, ...rest }) => 
  config.environment == 'master' ? rest : { stack, ...rest }
}))

app.listen(3000, () => console.log('程序启动在3000端口了'))
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352