阅读 137

结合Vue、node、mongodb讲述时间

时间

结合Vue、node、mongodb讲述时间

作者:临安啊
介绍:本文章,会以循序渐进的方式,讲述时间在vue和mongodb中的使用。 ps: 本文是作者在使用vue页面中使用时间对象后,扩展学习的如何在后台处理时间相关数据,希望分享出来加深对知识点的理解。有理解错误的地方欢迎指出!

可能本篇文章的知识点比较基础(作者需要努力努力再努力),可以抱着回忆知识点的心态来看待本文哈哈。

在vue页面上展示时间

简单地将时间输出到页面上

<!--html-->
<template>
  <div id="app">
    <p>现在的时间是: "{{ t }}"</p>
  </div>
</template>
复制代码
  • 通过浏览器的console,获取时间戳。

+new Date()

1583572995496

<!--script-->
data(){
    return{
      t:1583572995496
      }
}
复制代码

不过现在页面上输出的是时间戳,需要将它格式化一下输出。

  • 利用filter过滤器函数,为时间换上新装,格式化时间。

Tip: 为什么用filter而不是用computed?
因为filter 无法缓存,调用频率高,适合在格式发生变化,类似时间的转换,汇率的转换之类的,数据本身不变的一般就用filter。
而computed 计算属性背后的处理逻辑比较复杂,适合在复杂的数据转换、统计计算等时候使用。

<div id="app">
    现在的时间是 {{ t | format_date }}  //使用filter,要使用管道的方式为filter传参
</div>
复制代码

管道,用法和 linux 管道里面的是一样的,上一个的输出是下一个执行的输入

<!--script-->
<!--filters可以有很多个的-->
filters:{
    format_data(value){ //根据原来的date,格式化一下
        const date = new Date(value); //将时间戳交给一个new Date(),它会将
        return `${date.getFullYear()}${date.getMonth()+1}${date.getDate() }日`
     }
  }
复制代码
  1. const date = new Date(value); 将时间戳交给一个new Date(),它会变成一个日期对象。
  2. 通过日期对象的方法,返回年月日。如date.getFullYear()返回年份,注意月份是从0开始的,所以要加上一。

升级一下

  • 过滤器还可以全局声明,直接注册在vue上,就不用在每个组件中都声明了。
<!--main.js-->
Vue.filter('format_date',function format_date(value){ //后面是一个过滤器的回调函数
  const date =new Date(value);
  console.log(date);
  return `${date.getFullYear()}${date.getMonth()+1}${date.getDate() }${date.getHours()}${date.getMinutes()}${date.getSeconds()} 秒`;
})
复制代码

Moment

  • 除了用日期对象的方法将日期格式化,还能用 moment 对日期进行格式化。

Moment.js是JavaScript 日期处理类库,使用的方法很简单。

使用时只需要安装这个库yarn add moment,然后在需要使用的页面导入就能用了

导入:import moment from 'moment'

return moment().format('YY-MM-DD HH:mm:ss')
复制代码

  • moment有两种格式化当前时间的方式,两种方式得到的结果是一样的
<div>moment 1.格式化当前时间{{moment().format('YY-MM-DD HH:mm:ss')}}</div>
<div>moment 2.格式化当前时间{{moment(Date.now()).format('YYYY-MM-DD HH:mm:ss')}}</div>
复制代码

注意:mm和ss必须小写!hh是使用12小时时间制,HH时24小时时间制。

  • Moment插件的优点
  1. Moment 被设计为在浏览器和 Node.js 中都能工作。
  2. Moment中有很多支持对时间的复杂操作的方法,使用它还可以创建日历项目等复杂的日期时间应用。
  3. Moment 操作方式简单,使得对时间的处理变得简单。

注意:

  1. 导入只能在格式化数据的文件中引入,不可全局声明。
  2. 不支持转换中国的阴历农历。

用Moment处理时间

  1. 使用diff将当前时间与moment(t)时间产生比较,产生距上次过去了多长时间的效果。
<div>过去了{{moment().diff(moment(t), 'minutes')}}分钟</div>
//计算秒,将后面的minutes改成seconds就行,其他类似
复制代码
  1. 利用add,增加年数,月数,日数。
<div>2020-02-29的两年后是{{moment('2020-02-29').add(2,'year').format('YYYY-MM-DD HH:mm:ss')}}</div>
<div>2020-02-29的三个月后是{{moment('2020-02-29').add(3,'month').format('YYYY-MM-DD HH:mm:ss')}}</div>
<div>2020-02-29的四天后是{{moment('2020-02-29').add(4,'day').format('YYYY-MM-DD HH:mm:ss')}}</div>
复制代码

Node,在后台处理时间

有些什么地方是需要在后台处理时间的呢?比如数据存储在mongodb中,需要存储的数据中包括时间数据,比如做完了事情需要打上的时间戳等等。

<!--models/movie.js-->
const mongoose = require('mongoose');

//数据库存放在我们的硬盘中,这时候是一个物理模型,在物理模型之前的是模型(逻辑模型
const todoSchema = mongoose.Schema({
    title: {
        type: String,
        required: true,
    },
    address:String,
    content:String,
    // 开始和结束的日期 后端node的日期处理
    start: {
        type: Date,
        default: Date.now() //mongodb可以解析Date.now()
    },
    end: {
        type: Date,
        default: Date.now() //mongodb可以解析Date.now()
    },
    //大多数表的时间类型的声明
    created_at: { //创建的时间
        type: Date, //模型类型校验,在存入是校验是否是Date型数据
        default:Date.now //默认是当前时间,这样就不用传了,调用mongoodb的Date.now()函数,当前时间
    },
    update_at:{ //更新时间
        type: Date,
        default: Date.now
    }
})
//向外输出
const Todo = mongoose.model('Todo',todoSchema);//Todo,这样就有我们的模型类了,这个模型类再用save方法就能通过mongoose保存
module.exports = Todo //向外输出模型对象
复制代码

在mongoodb中存储时间

mongodb接受js的运行环境。mongodb本身对日期是支持函数式的操作的。

> Date()
Thu Mar 05 2020 17:53:54 GMT+0800 //本地化的当前时间
复制代码
> new Date() //得到ISO的时间戳
ISODate("2020-03-05T09:55:10.737Z") //mongodb中的日期格式
复制代码

比较Date()与new Date()的时间格式

> typeof Date()
string
> typeof new Date()
object
复制代码

可以看到两者相差了差不多8个小时,没错,就是时区的原因,是中国东八区时区。

由于mongo中的date类型以UTC(Coordinated Universal Time)存储,就等于GMT(格林尼治标准时)时间。而我当前所处的是东八区,所以mongo shell会将当前的GMT+0800时间减去8,存储成GMT时间。所以我们用new Date()查询到的iosdate的GMT时间。

ISO的日期类型可以直接使用new Date来进行比较,直接使用获取的时间+8后即可。

> ISODate("2020-03-05T09:55:10.7327Z").valueOf()
1583402110733 
复制代码

即使数据库中才能的是IOSDate,但是我们依然可以用IOSDate().valueOf()得到时间戳,然后再用new Date()可以得到正确的时间。

需要注意到的是,new Date(1583585563232)在mongodb中是返回的依旧是GTM,而当它在前端调用时返回的才是正确时间。不要搞混了!(我就搞混了哈哈)

  • 调用toLocaleString()方法,会把一个GTM时间转换成本地化的当前时间(加上区时)
ISODate("2020-03-06T09:42:26.680Z").toLocaleString();
Friday, March 06, 2020 17:42:26
复制代码

将时间数据插入mongodb中

  • 将时间插入mongodb的tests数据库(不是前面建的todo数据库)的tb1表中(这里是简单的用一个数据库演示如何插入和查询插入的时间)。
> use tests;
switched to db tests
> db.tb1.insert({mydate: ISODate("20121102 07:58:51")});//插mydate数据字段中
WriteResult({ "nInserted" : 1 })
> db.tb1.find();
{ "_id" : ObjectId("5e60d07a31a7cf46e9defe57"), "mydate" : ISODate("2012-11-02T07:58:51Z") } 
> db.tb1.insert({mydate: ISODate("20191101 07:58:51")});
WriteResult({ "nInserted" : 1 })
> db.tb1.find();
{ "_id" : ObjectId("5e60d07a31a7cf46e9defe57"), "mydate" : ISODate("2012-11-02T07:58:51Z") }
{ "_id" : ObjectId("5e60d0c231a7cf46e9defe58"), "mydate" : ISODate("2019-11-01T07:58:51Z") }
复制代码

存入的数据库的时间是ISODate时间格式

插入数据时,一定要先进入数据库。

use tests;

如果tests数据库之前不存在,会自动创建一个tests数据库。

  • 查询大于等于某时间,小于某时间:
<!--new Date()里面都是我们的时间戳-->
> db.tb1.find({mydate: { $gte: new Date(1351843131000) }});
{ "_id" : ObjectId("5e60d0c231a7cf46e9defe58"), "mydate" : ISODate("2019-11-01T07:58:51Z") }
> db.tb1.find({mydate: { $lt: new Date(1351843131100) }});
{ "_id" : ObjectId("5e60d07a31a7cf46e9defe57"), "mydate" : ISODate("2012-11-02T07:58:51Z") }
复制代码

在mongodb中以$开头的就是我们的查询条件,就像我们vue里面的指令一样v-if,v-for。 $gte就是大于等于equal, 没有e就是不能等于。

mongodb+node

为前面的todo数据库存入时间

<!--routes/index.js 到路由中处理交互-->
const express = require('express'); //express生成路由
const router = express.Router();
const mongoose = require('mongoose');
const ObjectId = mongoose.Types.ObjectId;
// console.log(typeof ObjectId);??出不来?
const moment = require('moment');
const Todo = require('../models/todo');//将模型层的todo.js引入
//用post表示新增一个对象,表单提交
router.post('/', (req, res) => {
  // 存时间时, 给日期的字符串 html表单的提交 
  // console.log(req.body); //请求体
  //调用mongoose里的create方法,创建一条物理的存储实例
  // 每次到达后,字节流数据json化一下(post请求是慢慢到达的,get请求不会去处理),放req.body中去
  Todo.create(req.body, (err, todo) => {  //存完后通过一个回调函数看看是否存储成功
    if (err) {
      res.json(err)
    } else { //存储完了把存储的东西再取出来一下
      res.json(todo)
    }
  }) //数据库是BSON文件,一个数据就是一个doc
})

router.get('/:id',(req,res)=>{ //使用id查询,参数路由
  const id = req.params.id; //id是一个参数
  Todo.findOne({
    "_id" : ObjectId(id) //"_id",是mongodb中会自动生成的,由hash字符串生成的
  }, (err, todo)=> {
    console.log(todo.start)
    console.log(new Date(todo.start).getMonth()+1)
    console.log(moment(todo.start).format('MMMM Do YYYY, h:mm:ss a'))
    res.json({
      err,
      todo
    })
  })
})
//要向外输出路由对象
module.exports = router
复制代码

要启动router,就要启动web服务器app.js

小思路:

  1. port 端口,写好访问的api端口。
  2. 进行数据库连接
const express = require('express');
const app = express();
const config = require('./config'); //专门用来连接数据库 
const bodyParser = require('body-parser'); //第三方库,中间件处理,解析传过来的东西,要拿到用来处理表单的提交,使用时要yarn add的。
const todo = require('./router/index'); //路由引入
const mongoose = require('mongoose');
mongoose.connect(config.mongodb);//连接数据库

//因为http请求是以字节流的形式传送的,所以要在postman中查看post过来的数据,要先json化一下
app.use(bodyParser.json()) 
//将沿着url传过来的数据进行编码,extended=true,要扩展一下
app.use(bodyParser.urlencoded({ extended: true}))

//启用路由
app.use('/todo', todo);

app.listen(config.port, () => {
  console.log(`listening on port ${config.port}`);
})
复制代码
  1. 处理路由是由一个个中间件来处理的,并且是按序处理, 比路由更早去处理http请求(有三次握手,请求数据以字节流传输)头数据的收集,所以
app.use(bodyParser.json()) //POST请求是慢慢到达的,GET请求的不会处理
app.use(bodyParser.urlencoded({ extended: true})) //将沿着url传过来的数据编码
复制代码

写在路由前面。
2. 原生node.js中,传输过来的数据会触发事件: on('data'),数据加载完成后触发事件: on('loaded')。
那根据什么判断表单传过来的数据都传完了?
因为在第一次发送的是请求头,会先到达,请求头中包含url,以及要发送过去的请求体的length(大小)。 每次到达后,就会去比较到达的数据数量和请求头中发送的length,如果数据大小一样,说明都发送完了。就会触发on('loaded')事件,然后交给后面的中间件,在这个中间件中就能拿到经过body-paser解析过来的内容,所以在到达路由前要有body-paser吧传过来的数据json化一下。

小提示,改了中间件之后要记得重启一下项目。

  1. 调用Todo.create()mongoose的create方法,会帮我们创建一条物理的存储实例,一个记录就是一个DOC,存什么进去?就把req.body,请求体中的数据存进去,存完后用回调函数看是否成功

根据object ID查询

router.get('/:id',(req,res)=>{ //使用id查询
  const id = req.params.id; //id是一个参数!
  Todo.findOne({
    "_id" : ObjectId(id) //"_id",是mongoose中会自动生成的,由hash字符串生成的
  }, (err, todo)=> {
    console.log(todo.start)
    console.log(new Date(todo.start).getMonth()+1)
    console.log(moment(todo.start).format('MMMM Do YYYY, h:mm:ss a'))
    res.json({
      err,
      todo
    })
  })
})
复制代码

PS:

  1. ObjectId记得事先定义:const ObjectId = mongoose.Types.ObjectId;
  2. const id = req.params.id; 而不是const id = req.query.id;
    我们的 "_id",是mongoose中会自动生成的,由hash字符串生成的,id作为参数传进来。

查询成功!

这里是结尾

本文是围绕时间,讲述vue+node+mongodb的关于时间的内容,知识点可能不够深入,其中有不完善的地方欢迎评论指出!谢谢阅读~