VueCli+Node+mongodb打造我的博客(含前台展现及后台管理系统)(中)

前言

前文:VueCli+Node+mongodb打造我的博客(含前台展现及后台管理系统)(上)
https://segmentfault.com/a/11...css

github地址:https://github.com/ssevenk/ss...前端

在上篇文章中
咱们完成了后端的配置,实现了对数据的增删查改
如今只须要前端页面发送对应的请求给后端便可vue

引入axios

在开始搭建组件前,咱们先要肯定前端异步请求的方式
这里我用的是axios
先在main.js中将其引入ios

import axios from 'axios'
Vue.prototype.$axios = axios;

这样咱们就能够在自定义的组件中,直接用this.$axios来发起异步请求git

后台管理系统

图片描述

这里我把它分红了两个组件
管理组件(Manage.vue)以及编辑组件(Edit.vue)github

管理组件(Manage.vue)

该组件的页面显示如图vue-router

clipboard.png
核心部分就是那个表格了
用来展现已经存在的数据并对其进行操做mongodb

左侧导航

分红了三个类别,文章,杂谈和收藏
当咱们点击对应的类别时,并无在切换组件,而是在更新数据
Manage.vue
咱们定义一个名叫things的空数组,来保存当前须要显示的数据
以及一个kind值,来保存当前须要显示的数据种类
咱们先令kind值为blog,默认显示 “文章” 数据axios

data() {
return {
  kind: "blog",
  things: [],
  }

当组件初始化时,调用生命周期函数created()向后端发起对应种类的请求
后端返回对应的数据,存进things里面segmentfault

created() {
        this.getData("blog"); //第一次默认先获取文章的数据
      },
    methods: {
      getData(kind) {
          this.kind = kind;
          this.$axios.get(`/data/${kind}`)
            .then(res => {
              this.things = res.data;
            })
     }

每次点击左侧的导航栏上的按钮,就调用一次getData(),并传入对应的kind参数
由此来更新thingskind
更新要显示的数据和种类
好比点击杂谈的话,就调用getData(essay)

数据表格

这里我用了Element-ui的组件库来制做表格
基本上就是官方案例

clipboard.png
能够看到跟个人效果基本上同样
因此这部分能够直接参考官网教程https://element.eleme.cn/#/zh...
在数据绑定的时候,选择咱们以前建好的things数组

:data='things'

搜索

右上角有一个搜索输入框
输入后能够即时显示搜索的结果在数据表格里
一开始我想新定义一个show数组,来存放搜索后的结果
而后给输入框绑定键盘事件来调用搜索函数
但后来发现Element官网的作法异常简单
能够直接在el-table表格绑定的数据上作文章

:data="((things.filter(data=>!search||data.title.toLowerCase().includes(search.toLowerCase())“

其中search是双向绑定在输入框上的数据

分页

数据太多了确定须要分页
仍是用到了咱们的Element-ui组件库

<el-pagination
        @current-change="handleCurrentChange"
        :page-size="pageSize"
        :current-page="currentPage"
        :total=" things.length"
        layout="total, prev, pager, next"
      ></el-pagination>

PageSize设置为5,当前默认页为1

data() {
return {
  kind: "blog",
  things: [],
  currentPage: 1,
  pageSize: 5,
  search: ""
};}

当点击页码切换的时候,把页码更新

handleCurrentChange(currentPage) {
  this.currentPage = currentPage;
}

而后再一次对咱们以前的el-table标签上的数据进行改进

:data="((things.filter(data=>!search||data.title.toLowerCase().includes(search.toLowerCase())).slice((currentPage-1)*pageSize,currentPage*pageSize)))"

这里的逻辑前后要理清
是先对数据进行搜索的过滤再分页

编辑组件(Edit.vue)

比起展现,更重要的仍是对数据的操做
这里我把新建和编辑功能整合进了同一个组件里
由于都是利用markdown编辑器来编写
布局如出一辙,只有初始化,按钮以及请求的方式不同

clipboard.png
关于这个markdown编辑器,我是利用的simpleMDE
并添加了原本没有的本地上传图片功能
能够参见个人另外一篇文章https://segmentfault.com/a/11...
这里再也不重复说明
其中在样式上,为了使编辑器高度控制在页面内,使滚动条出如今编辑器内而不是页面

.CodeMirror-scroll {
  min-height:350px;
  height: 350px;
}

添加这样的css样式(原本默认是800px)

新建仍是编辑?

Mangage组件中点击了新建或者某篇文章的编辑按钮
咱们就进入了这个Edit组件
由于整合在了同一个组件中
因此首先它得判断如今是要新建仍是编辑
以及是要处理哪一种数据,文章仍是杂谈仍是收藏?
创建一个boolisNew和一个stringkind
而后在生命周期函数created()中进行判断

created() {
    this.kind = this.$route.params.kind;
    if (this.$route.params.id != "new") {
      this.isNew = false;
    }
  },

根据Manage组件路由跳转时传入的参数来判断
关于vue-router路由跳转,若是对queryparams的用法有所疑问,能够参考个人这篇文章https://segmentfault.com/a/11...

按钮

按钮给一个函数让其自行计算应该显示什么文字

computed: {
btn: function() {
  switch (this.kind) {
    case "blog":
      return (this.isNew ? "发表" : "更新") + "文章";
    case "essay":
      return (this.isNew ? "发表" : "更新") + "杂谈";
    case "article":
      return (this.isNew ? "发表" : "更新") + "收藏";
    default:
      return "";
  }
}

若是是编辑

mounted()周期函数中,请求后端的数据,来填入markdown编辑器的输入框

if (!this.isNew) {
      this.$axios
        .get(`/data/${this.$route.params.kind}/${this.$route.params.id}`)
        .then(req => {
          this.title = req.data.title;
          this.content = req.data.content;
          this.comments=req.data.comments;
          simplemde.value(this.content);
        });
    }

编辑完成后对后端的post请求

if (!this.isNew) {
        this.$axios
          .post(`/data/${this.$route.params.kind}/${this.$route.params.id}`, {
            id: this.$route.params.id,
            title: this.title,
            content: this.content
          })

若是是新建

须要给新文章一个创做日期

computed:{
    date: function() {
          var time = new Date(this.time);
          return `${(time.getMonth() + 1).toString().padStart(2, "0")}-${time
            .getDate()
            .toString()
            .padStart(2, "0")}`;
        }}

为了美观,用padStart来保证个位很多天期也能以两位输出
post的时候,把日期也加上

this.$axios
          .post(`/data/${this.$route.params.kind}/new`, {
            title: this.title,
            content: this.content,
            comments:this.comments,
            date: this.date
          })

删除数据

点击删除按钮的时候,获取到对应数据的id值并向后端传递
不过在这以前要先找到这个数据在things中的位置并删除
使用findIndexsplice

del(delid) {
  var delIndex = this.things.findIndex(item => {
    return item._id == delid;
  });
  this.things.splice(delIndex, 1);
  this.$axios.delete(`/data/${this.kind}/${delid}`);
}

PS.

其实后来我又写了一个EditArticle组件出来
对应”收藏“,由于它只须要标题和跳转的连接,不须要编辑器
因此就单独为它写了一个,原理类同,这里再也不赘述

接下来

完成了后台管理系统
咱们就要开始作展现页面了
敬请期待后续文章

已更新第三篇:https://segmentfault.com/a/11...

相关文章
相关标签/搜索