从零到一开发博客后台管理系统
1.今日计划完成
- home页顶栏设计
- home页tab标签页与左侧导航栏动态菜单联动
- axios的封装
2.home页顶栏设计
只是用于显示标题,看起来干净一些
我们来编辑top.vue
<template>
<div>
<span class="title">博客管理系统</span>
</div>
</template>
.title {
margin-left: 1.25rem;
cursor: pointer;
}
现在的效果是这样的
3.home页标签页的设计
我们这里设计9个标签页,分别是:随笔 文章 日记 评论 链接 相册 文件 设置 选项
每一个标签页的选项应该对应一个组件,现在先用文字来代替,以后做到对应的组件在来替换
编辑完main.vue之后是这样的
<template>
<div class="tab">
<el-tabs type="card">
<el-tab-pane label="随笔">随笔</el-tab-pane>
<el-tab-pane label="文章">文章</el-tab-pane>
<el-tab-pane label="日记">日记</el-tab-pane>
<el-tab-pane label="评论">评论</el-tab-pane>
<el-tab-pane label="链接">链接</el-tab-pane>
<el-tab-pane label="相册">相册</el-tab-pane>
<el-tab-pane label="文件">文件</el-tab-pane>
<el-tab-pane label="设置">设置</el-tab-pane>
<el-tab-pane label="选项">选项</el-tab-pane>
</el-tabs>
</div>
</template>
没错就是如此简单,现在我们来看一下效果吧
4.左侧的导航栏
导航栏我们可以根据选中的标签不同,显示不同的动态菜单
我们先来设计一下我们的菜单吧
- 标签选中随笔
× 博客操作- 新建随笔
- 草稿箱
- 博客签名
- 博客备份
- 博客搬家
- vue
- python
- 。。。
- 标签选中文章
× 文章操作- 新建文章
- 草稿箱
- 文章备份
- vue
- python
- 。。。
- 标签选中日记
× 日记操作- 新建日记
- 阅读日记
- 日记备份
- 标签选中评论
- 我发表过的评论
- 我参与的随笔
- 旧版留言
- 订阅评论通知的博文
由于后面的链接 相册 文件 设置 选项过于复杂,本次版本不做处理(如果搞得太复杂很可能太监掉)
选到这些我们暂时用同意的页面来提示
那么现在在src下新建文件夹config,新建文件home.json,写入上面的信息
这是我的json文件(home.json)
{
"InformalEssay_Menu": [{
"index": "1",
"name": "博客管理",
"url": "",
"children": [{
"index": "1-1",
"name": "新建随笔",
"url": ""
}, {
"index": "1-2",
"name": "草稿箱",
"url": ""
}, {
"index": "1-3",
"name": "博客签名",
"url": ""
}, {
"index": "1-4",
"name": "博客备份",
"url": ""
}, {
"index": "1-5",
"name": "博客搬家",
"url": ""
}]
},
{
"index": "2",
"name": "分类管理",
"url": "",
"children": [{
"index": "2-1",
"name": "vue",
"url": ""
}, {
"index": "2-2",
"name": "python",
"url": ""
}, {
"index": "2-3",
"name": "java",
"url": ""
}]
}
],
"Article_Menu": [{
"index": "1",
"name": "文章管理",
"url": "",
"children": [{
"index": "1-1",
"name": "新建文章",
"url": ""
}, {
"index": "1-2",
"name": "草稿箱",
"url": ""
}, {
"index": "1-3",
"name": "文章备份",
"url": ""
}]
},
{
"index": "2",
"name": "分类管理",
"url": "",
"children": [{
"index": "2-1",
"name": "vue",
"url": ""
}, {
"index": "2-2",
"name": "python",
"url": ""
}, {
"index": "2-3",
"name": "java",
"url": ""
}]
}
],
"Diary_menu": [{
"index": "1",
"name": "日记管理",
"url": "",
"children": [{
"index": "1-1",
"name": "新建日记",
"url": ""
}, {
"index": "1-2",
"name": "阅读日记",
"url": ""
}, {
"index": "1-3",
"name": "日记备份",
"url": ""
}]
}
],
"Commpent_Menu": [{
"index": "1",
"name": "评论管理",
"url": "",
"children": [{
"index": "1-1",
"name": "我发表过的评论",
"url": ""
}, {
"index": "1-2",
"name": "我参与的随笔",
"url": ""
}, {
"index": "1-3",
"name": "旧版留言",
"url": ""
}, {
"index": "1-4",
"name": "订阅评论通知的博文",
"url": ""
}]
}
],
"tab": {
"tab0": "InformalEssay_Menu",
"tab1": "Article_Menu",
"tab2": "Diary_menu",
"tab3": "Commpent_Menu"
}
}
只写了四个菜单,有兴趣的可以自己补充完整,那么我们如何将这些数据变成菜单呢?我们需要在home文件夹下面新建menutree.vue,这就是我们的菜单组件了。
<template>
<div class="menutree">
<label v-for="menu in data" :key="menu.index">
<el-submenu :index="menu.index" v-if="menu.children && menu.children.length">
<template slot="title">
<span>{{menu.name}}</span>
</template>
<label>
<menutree :data="menu.children"></menutree>
</label>
</el-submenu>
<el-menu-item v-else :index="menu.index" @click="select(menu)">
<span slot="title">{{menu.name}}</span>
</el-menu-item>
</label>
</div>
</template>
<script>
import menutree from "@/views/home/menutree";
export default {
name: "menutree",
data() {
return {
menu_data: {}
};
},
components: {
menutree: menutree
},
props: ["data"],
methods: {
select(menu) {
this.$router.push(menu.url);
}
}
};
</script>
<style scoped>
</style>
从我们的菜单数据中递归生成一个菜单树,详细的过程可以参考另一篇博客
接下来就是在left.vue中调用这个组件了,为了避免频繁的调用json文件,我们使用一个data参数来传递数据。
<template>
<div>
<el-menu>
<menutree :data="data"></menutree>
</el-menu>
</div>
</template>
<script>
import menutree from "@/views/home/menutree";
export default {
components: {
menutree: menutree
},
props: ["data"],
methods: {
select(menu) {
this.$router.push(menu.url);
}
}
};
</script>
接下来就是我们的index.vue组件了
只需要简单的改动一下left标签中添加 :data属性
<left :data="data"></left>
在js中添加data
import top from "@/views/home/top";
import left from "@/views/home/left";
import right from "@/views/home/main";
import data from "@/config/home.json";
export default {
data() {
return {
data: {}
};
},
components: {
top: top,
left: left,
right: right
},
mounted() {
this.data = data.InformalEssay_Menu;
},
}
现在我们的页面上应该已经有一个菜单栏显示了
当然这个时候,我们点击右面的标签,左边的菜单栏是不会有任何变化的。我们需要吧它们关联起来,这时,我们就需要了解一下组件间的通信了。
我们的信息都是在index.vue组件上处理的,所以main.vue上的标签被点击时需要向父节点传递信息,这种情景我们使用$emit这个方法来传递消息
在index.vue 组件中,为right标签添加属性
<right @change="change"></right>
定义change方法
methods: {
change(msg) {
this.data = data[data.tab[msg]];
}
}
上面的msg传递的是tab标签的唯一标识信息
接下来在main.vue中来传递这个消息
<template>
<div class="tab">
<el-tabs type="card" @tab-click="toParent">
<el-tab-pane label="随笔">随笔</el-tab-pane>
<el-tab-pane label="文章">文章</el-tab-pane>
<el-tab-pane label="日记">日记</el-tab-pane>
<el-tab-pane label="评论">评论</el-tab-pane>
<el-tab-pane label="链接">链接</el-tab-pane>
<el-tab-pane label="相册">相册</el-tab-pane>
<el-tab-pane label="文件">文件</el-tab-pane>
<el-tab-pane label="设置">设置</el-tab-pane>
<el-tab-pane label="选项">选项</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
export default {
methods: {
toParent(tab, event) {
let id = event.target.getAttribute("id").replace("-", "");
this.$emit("change", id);
}
}
};
</script>
由于tab默认的id是 tab-1这种命名方式,在这里我选择把中间的-过滤掉,变成tab1这种形式传递到父节点
这样tab标签就和菜单关联起来了
因为我们只写了前面四个标签的菜单数据,所以后面的标签是没有菜单的,点击左边是空白的,这样很不友好,先把他们注释掉
5.axios的封装
这个我参考了大量的博客,主要就是拦截器以及对各种请求方法的封装,写法比较固定
在axios文件夹下新建index.js文件
import axios from 'axios';
import { Message } from 'element-ui';
axios.defaults.timeout = 5000;
axios.defaults.baseURL ='http://127.0.0.1:8000';
//http request 拦截器
axios.interceptors.request.use(
config => {
// 发送数据之前的操作
return config;
},
error => {
return Promise.reject(err);
}
);
//http response 拦截器
axios.interceptors.response.use(
response => {
// 返回数据之前的操作
return response;
},
error => {
return Promise.reject(error)
}
)
/**
* 封装get方法
* @param url
* @param data
* @returns {Promise}
*/
export function fetch(url,params={}){
return new Promise((resolve,reject) => {
axios.get(url,{
params:params
})
.then(response => {
resolve(response.data);
})
.catch(err => {
reject(err)
})
})
}
/**
* 封装post请求
* @param url
* @param data
* @returns {Promise}
*/
export function post(url,data = {}){
return new Promise((resolve,reject) => {
axios.post(url,data)
.then(response => {
resolve(response.data);
},err => {
reject(err)
})
})
}
/**
* 封装patch请求
* @param url
* @param data
* @returns {Promise}
*/
export function patch(url,data = {}){
return new Promise((resolve,reject) => {
axios.patch(url,data)
.then(response => {
resolve(response.data);
},err => {
reject(err)
})
})
}
/**
* 封装put请求
* @param url
* @param data
* @returns {Promise}
*/
export function put(url,data = {}){
return new Promise((resolve,reject) => {
axios.put(url,data)
.then(response => {
resolve(response.data);
},err => {
reject(err)
})
})
}
如果需要封装其他的方法,写法都是一样的。
那么今天的内容就到此结束了,记录一下时间:19年5月22日 22:51
有任何疑问或者建议可以在下方留言