我们之前做了很多页面,包括注册登录和上传,但是目前并不能查看博客文章。因此这次我们需要做一个文章浏览页面。
动态路由匹配与文章获取
通常来讲,我们在浏览博客的时候访问的链接都是/article/id,而不是article?id=id,这就代表了我们不能通过链接传参的方式来获取对应的博客,而应该使用动态路由匹配。在pages文件夹下新建一个articleReading.vue组件,然后在路由中这样写:
{path: '/article/:id', component: articleReading}
当我们访问/article/1和/article/2的时候访问的就都是同一个路由了。对应的参数会绑定到$router对象中,想要显示链接中传入的id便可以直接调用对应的属性即可,像这样。
<template>
读文章{{ $route.params.id }}
</template>
搞到了文章id后,便可以在前后端分别写好对应的代码了,前端通过server/getArtile链接获取文章,后端通过传入的id来寻找对应的文章发送回去。这里的HTTP使用的是get指令而不是post,并不能包含body,因此我们依旧是通过传参的形式来获取文章。下面是后端的代码,很简单,注意一下express是如何传参的就可以了。
app.get('/getArticle/:id',(req, res)=>{
const id = req.params.id;
const selectSql = `select * from articles where id = '${id}'`;
connection.query(selectSql, (err, result)=>{
if(result.length === 0){
res.status(404).end();
}else{
const article = result[0];
res.send(article);
}
})
})
为了配合后端的express的参数形式,我们前端的代码最好就像这样:
<script setup>
import axios from 'axios';
import { useRoute } from 'vue-router';
const route = useRoute();
let article ={
title: '默认文章',
id: '0000000000000000',
author: '0',
createTime: 0,
content: '文章内容',
likes: 0,
}
axios.get(`/server/getArticle/${route.params.id}`)
.then((response)=>{
article = response.data;
})
.catch((err)=>{
alert(err);
})
console.log(route.params.id);
</script>
<template>
读文章{{ article.author }}
{{ article.content }}
</template>
这里的默认文章是为了配合JavaScript的作用域而设置的,同时也可以在页面未渲染完成时起到占位符的作用。
文章渲染
我们获取到了文章的全部内容后就需要进行渲染了。我们之前使用的是bytemd的编辑器,因此这边可以配套使用它的渲染。内容渲染结束后还有作者、创建时间、标题和点赞数的渲染。其中时间渲染我们使用luxon包来进行,这是一款开源的时间渲染包,直接导入时间戳就可以在前端把时间渲染成我们需要的格式。
<script setup>
import axios from 'axios';
import { useRoute } from 'vue-router';
import { Viewer } from '@bytemd/vue-next';
import { nextTick, ref } from 'vue';
import {DateTime} from 'luxon'
import 'bytemd/dist/index.css'
const route = useRoute();
let article =ref({
title: '默认文章',
id: '0000000000000000',
author: '0',
createTime: 0,
content: '文章内容',
likes: 0,
})
axios.get(`/server/getArticle/${route.params.id}`)
.then((response)=>{
article.value = response.data;
nextTick();
})
.catch((err)=>{
alert(err);
})
</script>
<template>
<h1>{{ article.title }}</h1>
<div>
作者:{{ article.author }}
</div>
<Viewer :value ="article.content" />
<div>
创建于{{ DateTime.fromMillis(Number(article.createTime)).toLocaleString(DateTime.DATE_MED)}}
</div>
</template>
首页文章
能够创建文章后,我们就可以在首页看文章咯。首先在后端写一个获取随机博客的接口/getRandomArticle。目前无需考虑效率和其它问题
app.get('/getRandomArticle',(req, res)=>{
const selectSql = `select * from articles`
connection.query(selectSql,(err,result)=>{
if(err){
res.status(500).send(`${err}`);
}else{
const index = Math.floor((Math.random()*result.length));
const article = result[index];
article.content = article.content.slice(0,20);
// 取前20个字作为预览内容。
res.send(article);
}
})
})
还记得前端的articlePreview组件么,接下来我们就要对它进行修改,当组件创建时,获取随机博客,根据博客的信息来生成博客预览。
<script setup>
import axios from 'axios';
import { ref } from 'vue';
import { useRouter } from 'vue-router';
const article = ref({
title: '默认文章',
id: '0000000000000000',
author: '0',
createTime: 0,
content: '文章内容',
likes: 0,
});
const router = useRouter()
axios.get('/server/getRandomArticle')
.then((response)=>{
article.value = response.data;
})
function linkToArticle(){
router.push(`/article/${article.value.id}`)
}
</script>
<template>
<div @click="linkToArticle">
{{ article.title }}
{{ article.content }}
</div>
</template>
<style>
</style>
至此一个基本的博客系统就做完了。在下一篇文章中我们将会开始进行外观的优化,也就是css的部分。