共计 3920 个字符,预计需要花费 10 分钟才能阅读完成。
前言
前文:VueCli+Node+mongodb 打造个人博客(含前台展示及后台管理系统)(上)
https://segmentfault.com/a/11…
github 地址:https://github.com/ssevenk/ss…
在上篇文章中
我们完成了后端的配置,实现了对数据的增删查改
现在只需要前端页面发送对应的请求给后端即可
引入 axios
在开始搭建组件前,我们先要确定前端异步请求的方式
这里我用的是 axios
先在 main.js
中将其引入
import axios from 'axios'
Vue.prototype.$axios = axios;
这样我们就可以在自定义的组件中,直接用 this.$axios
来发起异步请求
后台管理系统
这里我把它分成了两个组件
管理组件(Manage.vue
)以及编辑组件(Edit.vue
)
管理组件(Manage.vue)
该组件的页面显示如图
核心部分就是那个表格了
用来展示已经存在的数据并对其进行操作
左侧导航
分成了三个类别,文章,杂谈和收藏
当我们点击对应的类别时,并没有在切换组件,而是在更新数据
在Manage.vue
中
我们定义一个名叫 things
的空数组,来保存当前需要显示的数据
以及一个 kind
值,来保存当前需要显示的数据种类
我们先令 kind
值为blog
,默认显示“文章”数据
data() {
return {
kind: "blog",
things: [],}
当组件初始化时,调用生命周期函数 created()
向后端发起对应种类的请求
后端返回对应的数据,存进 things
里面
created() {this.getData("blog"); // 第一次默认先获取文章的数据
},
methods: {getData(kind) {
this.kind = kind;
this.$axios.get(`/data/${kind}`)
.then(res => {this.things = res.data;})
}
每次点击左侧的导航栏上的按钮,就调用一次 getData()
,并传入对应的 kind 参数
由此来更新 things
和kind
更新要显示的数据和种类
比如点击杂谈的话,就调用getData(essay)
数据表格
这里我用了 Element-ui
的组件库来制作表格
基本上就是官方案例
可以看到跟我的效果基本上一样
所以这部分可以直接参考官网教程 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 编辑器来编写
布局一模一样,只有初始化,按钮以及请求的方式不一样
关于这个 markdown
编辑器,我是利用的 simpleMDE
并添加了本来没有的本地上传图片功能
可以参见我的另一篇文章 https://segmentfault.com/a/11…
这里不再重复说明
其中在样式上,为了使编辑器高度控制在页面内,使滚动条出现在编辑器内而不是页面
.CodeMirror-scroll {
min-height:350px;
height: 350px;
}
添加这样的 css
样式(本来默认是 800px)
新建还是编辑?
在 Mangage
组件中点击了新建或者某篇文章的编辑按钮
我们就进入了这个 Edit
组件
因为整合在了同一个组件中
所以首先它得判断现在是要新建还是编辑
以及是要处理哪种数据,文章还是杂谈还是收藏?
建立一个 bool
值isNew
和一个 string
值kind
然后在生命周期函数 created()
中进行判断
created() {
this.kind = this.$route.params.kind;
if (this.$route.params.id != "new") {this.isNew = false;}
},
根据 Manage
组件路由跳转时传入的参数来判断
关于 vue-router
路由跳转,如果对 query
和params
的用法有所疑问,可以参考我的这篇文章 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
中的位置并删除
使用 findIndex
和splice
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…