现在我们可以登录注册发文章,但是怎么看自己都写了什么文章呢?我们需要一个个人中心。个人中心还存储着用户的个性签名、生日和头像等。
嵌套路由
一般来讲,一个人的个人空间链接为/space/:userid,“我的文章”链接为/space/:userid/articleList。可以想到在个人空间链接下面还有很多个嵌套的子路由。Vue-router自然是支持的,也很简单。我们只要在对应的路由节点组件中添加一个childeren数组,内容就和通常的节点一样即可。
const routes =[
{path: '/', component: home},
{path: '/register', component: register},
{path: '/login', component: login},
{path: '/articleEditor', component: articleEditor},
{path: '/article/:id', component: articleReading},
{path:'/space/:id',component: space, children:[
{path:'articles', component: articleList},
]}
]
在登录的时候才会显示个人中心的按钮。但是这里存在一个问题:我们目前只有用户的邮箱,并没有用户的ID,这边打算使用MD5后的邮箱的前10位作为ID(你也不想顶着邮箱上网吧),因此这边需要扩展一下后端,使其包用户id。
app.get('/test',(req, res)=>{
const sql = 'alter table useraccount add id varchar(10)';
connection.query(sql,(err,result)=>{
console.log(result);
})
})
app.post('/register',(req, res)=>{
const captcha = req.body.captcha;
if(!checkCaptcha(captcha, req.session.captcha)){
req.session.captcha ='';
res.status(400).send('验证码错误');
return;
}
const email = req.body.email;
const username = req.body.username;
let password = req.body.password;
password = SHA512(password).toString();
const id = MD5(email).toString().slice(0,10);
const addSql=`insert into useraccount (email, username, password, id) values(?,?,?,?)`;
const selectSql = `select * from useraccount where email = '${email}'`;
connection.query(selectSql,(err,result)=>{
if(result.length!==0){
res.status(400).send('邮箱已被占用');
}else{
connection.query(addSql,[email, username, password, id],(err)=>{
if(err){
res.status(500).send(`注册失败, ${err}`);
}else{
res.send('注册成功');
}
})
}
})
})
既然我们已经有了id,那么前端便不应该存储用户邮箱了,而应该是用户的id。因此我们需要推翻上一篇文章中的前端代码。虽然看上去有一些重复劳动,但是这便是敏捷开发带来的额外负担,我们不得不承受。同时为了防止数据库报错,我们还需要清空原数据库中的数据(反正都是些测试数据),SQL中清空数据表的语句为truncate table TABLENAME。这里就不给出具体代码了。
前期的准备工作都做完了,我们就可以创建用户中心页面了。用户中心页面中也需要一个router-view作为嵌套路由的页面显示。
<script setup>
import { useRoute } from 'vue-router';
const route = useRoute()
</script>
<template>
<h1>个人中心</h1>
<router-view></router-view>
</template>
<style scoped>
h1{
margin-top: 0;
}
</style>
导航守卫
非本人用户和本人用户空间所需要的功能是不一样的,这就导致我们不能用同一套组件传入不同的id。我们需要先创建一个mySpace.vue组件,然后创建对应的路由。并且当/space/:id中的id等于目前登录的id时,路由就会将链接重定向至/mySpace。
Vue-Router自然也支持这个功能,这便是导航守卫。可以注册全局导航守卫,也可以给特定的路由注册专属的导航守卫。目前route的代码比较多了,可以单独抽离出来成为一个route.js。
导航守卫的优点在哪呢?就在于它会在路由跳转前就进行对应的判断,而不是路由跳转之后再进行判定,因此不用再加载对应页面的资源。在实际的生产环境中,很少会单独给一个路由设定守卫,通常都使用全局守卫,因此我们先给/articleEditor添加守卫,代替页面本身的登录判断。
const userAccountStore = useUserAccountStore();
router.beforeEach( (to, from)=>{
if(to.path === '/articleEditor' && !userAccountStore.isLogged){
alert('您还未登录,请先登录!');
return false;
}
})
发现会报错,报错的竟然是pinia。这是因为vue插件是异步加载的,pinia还没有被挂载到实例上,而vue-router就被加载了,这就会报错。因此我们先把pinia实例引入到route.js上,这样就可以遵循正确的顺序了。这是store.js的代码:
import {createPinia} from 'pinia'
const pinia = createPinia();
export{
pinia
}
route.js中把引入pinia修改一下即可。
import { pinia } from '../stores/store'
const userAccountStore = useUserAccountStore(pinia);
此时我们就可以判定个人空间了,如果即将访问的个人空间id是自己的,那么就会被重定向到/mySpace页面。