博客前台
博客列表
列表项组件
补充列表项组件: frontend/BlogItem.vue
<template>
<div>
<h2 class="title">
{{ title }}
</h2>
<div class="describe">
<div>发表于: {{ publishAt }}</div>
<a-divider direction="vertical" />
<div>作者: {{ author }}</div>
</div>
<div class="summary">
{{ summary }}
</div>
<div class="more">
<a-button size="mini" type="dashed">阅读全文 »</a-button>
</div>
</div>
</template>
<script setup>
defineProps({
title: String,
publishAt: Number,
author: String,
summary: String,
});
</script>
<style lang="less" scoped>
.title {
display: flex;
justify-content: center;
align-items: center;
align-content: center;
color: #555;
}
.describe {
display: flex;
justify-content: center;
align-items: center;
align-content: center;
color: #999;
font-size: 12px;
}
.summary {
color: #333;
font-size: 14px;
line-height: 1.6;
margin: 10px 0 10px 0;
}
.more {
display: flex;
justify-content: center;
align-items: center;
align-content: center;
}
</style>
列表页
博客列表页: frontend/BlogView.vue
<script setup>
import BlogItem from "./BlogItem.vue";
</script>
<template>
<div class="content">
<a-space direction="vertical" style="width: 700px">
<BlogItem
title="测试"
publishAt="1662978665"
author="测试"
summary="Java启动命令是所有java应用程序的入口,通过它来启动Java运行时环境,并加载相关的class。不过由于IDE的盛行,我们Java程序员中的大多数并不是非常的了解Java启动命令。本文希望做一个Java启动命令的汇总,和各位同道分享,也便于日后作为自己的参考"
></BlogItem>
<BlogItem
title="测试"
publishAt="1662978665"
author="测试"
summary="测试"
></BlogItem>
<BlogItem
title="测试"
publishAt="1662978665"
author="测试"
summary="测试"
></BlogItem>
</a-space>
</div>
</template>
<style lang="less" scoped>
.content {
width: 100%;
}
</style>
博客详情页
由于博客是 Markdown 的, 所以我们需要选择一个支持 Markdown 编辑与展示的 Vue3 的库: 这里选择使用md-editor-v3
md-editor-v3库介绍
安装md-editor-v3:
npm i md-editor-v3
使用方法:
<template>
<md-editor v-model="text" preview-only />
</template>
<script setup>
import { ref } from 'vue';
import MdEditor from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
const text = ref('# Hello Editor');
</script>
详情页组件
frontend/BlogDetail.vue
<template>
<div>
<h2 class="title">
{{ title }}
</h2>
<div class="describe">
<div>发表于: {{ publishAt }}</div>
<a-divider direction="vertical" />
<div>作者: {{ author }}</div>
</div>
<div style="width: 700px">
<md-editor
v-model="text"
preview-only
style="height: calc(100vh - 85px)"
/>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
import MdEditor from "md-editor-v3";
import "md-editor-v3/lib/style.css";
const title = "测试";
const publishAt = 10000;
const author = "测试";
const text = ref(`## 参考
+ [博客样式参考](http://www.arccode.net/)
+ [md-editor-v3 官方页面](https://imzbf.github.io/md-editor-v3/index)
+ [md-editor-v3 Github](https://github.com/imzbf/md-editor-v3)`);
</script>
<style lang="less" scoped>
.title {
display: flex;
justify-content: center;
align-items: center;
align-content: center;
color: #555;
}
.describe {
display: flex;
justify-content: center;
align-items: center;
align-content: center;
color: #999;
font-size: 12px;
}
</style>
在 index.js 中添加子路由
{
path: "/frontend",
name: "frontend",
component: FrontendLayout,
children: [
{
path: "blogs",
name: "BlogView",
component: () => import("@/views/frontend/BlogView.vue"),
},
{
path: "blogs/:id",
name: "BlogDetail",
component: () => import("@/views/frontend/BlogDetail.vue"),
},
],
},
列表页跳转
frontend/BlogItem.vue
阅读全文补充跳转:
<a-button size="mini" type="dashed" @click="jumpToDetail"
>阅读全文 »</a-button>
跳转到详情页
const router = useRouter();
const jumpToDetail = () => {
router.push({ path: `blogs/xxx` });
};
对接后端
在 src 目录里新建 api 目录 进行对后端的对接
新建 client.js
import axios from "axios";
const client = axios.create({
timeout: 5000,
});
// 添加请求拦截器,用于认证, 都需要携带 Token,或者 basic AUTH
client.interceptors.request.use(
(request) => {
return request;
},
(error) => {
console.log(error);
}
);
// 添加响应拦截器, 用于处理返回异常, code != 0
client.interceptors.response.use(
(response) => {
return response;
},
(error) => {
console.log(error);
}
);
export default client;
我们在 api文件夹内 新建 blog.js 存储对博客页面的操作
对接列表页
//blog.js
import client from "./client.js";
export function LIST_BLOG(params) {
return client({
url: "/vblog/api/v1/blog/",
method: "get",
params: params,
});
}
对 BlogView.vue 进行修改,使他从后端获取数据并显示
<script setup>
import BlogItem from "./BlogItem.vue";
import { LIST_BLOG } from "@/api/blog.js";
import { onMounted, ref } from "vue";
const blogs = ref([]);
onMounted(async () => {
try {
const resp = await LIST_BLOG();
blogs.value = resp.data.items;
} catch (error) {
console.log(error);
}
});
console.log(blogs);
</script>
<template>
<div class="content">
<a-space direction="vertical" style="width: 700px">
<div v-for="item in blogs" :key="item.id">
<BlogItem
v-if="item.status === 'published'"
:id="item.id"
:title="item.title_name"
:publishAt="item.publish_at"
:author="item.author"
:summary="item.summary"
></BlogItem>
</div>
</a-space>
</div>
</template>
<style lang="less" scoped>
.content {
width: 100%;
}
</style>
自己试试吧
对接详情页
在 blog.js 添加 GET_BLOG 方法
export function GET_BLOG(id, params) {
return client({
url: `/vblog/api/v1/blog/${id}`,
method: "get",
params: params,
});
}
修改 BlogItem.vue 的 script 部分
- 在
Props里新增id字段接收 URL 的id router.push通过路由名称和params的 id 组合
import { useRouter } from "vue-router";
const pros = defineProps({
id: Number,
title: String,
publishAt: Number,
author: String,
summary: String,
});
const router = useRouter();
const JumpToDetail = () => {
router.push({ name: "BlogDetail", params: { id: pros.id } });
};
大幅度修改 BlogDetail.vue
<template>
<div>
<h2 class="title">
{{ data.title_name }}
</h2>
<div class="describe">
<div>发表于: {{ data.publish_at }}</div>
<a-divider direction="vertical" />
<div>作者: {{ data.author }}</div>
</div>
<div class="summary">
{{ data.summary }}
</div>
<div style="width: 700px">
<md-editor v-model="data.content" preview-only />
</div>
</div>
</template>
<script setup>
import { onMounted, ref } from "vue";
import MdEditor from "md-editor-v3";
import "md-editor-v3/lib/style.css";
import { GET_BLOG } from "@/api/blog.js";
import { useRoute } from "vue-router";
const data = ref({});
onMounted(async () => {
try {
// id 从路由里面获取, 读取的路由对象
const route = useRoute();
console.log(route.params.id);
const resp = await GET_BLOG(route.params.id);
console.log(resp);
data.value = resp.data;
} catch (error) {
console.log(error);
}
});
</script>
<style scoped>
.title {
display: flex;
justify-content: center;
align-items: center;
align-content: center;
color: #555;
}
.describe {
display: flex;
justify-content: center;
align-items: center;
align-content: center;
color: #999;
font-size: 12px;
}
.summary {
margin: 8px;
color: #555;
}
</style>
试试吧!