首先要解决一个bug,点击文章分类下的标签tab
路由并不会跳转
后面点击某一个标签进行传值时就会出错,
所以应该修改activeName的set方法,使得小tab切换时,路由也能够切换
activeName:
{
get()
{
return this.currentActiveName = this.$route.params.type;
/*等于
this.currentActiveName = this.$route.params.type
return this.currentActiveName*/
},
set(newV)
{
this.currentActiveName = newV;
this.$router.push({path:`/${newV}/all`})
}
},
这里切换路由之后,又会第二次切换路由,会报错,但不影响运行,所以在router/index.js
下捕捉该异常
import Vue from 'vue'
import VueRouter from 'vue-router'
import foo from '../pages/foo'
import bar from '../pages/bar'
import Home from '@/home/Home'
Vue.use(VueRouter)
const router = new VueRouter({
routes:
[
{
path: '',
name: 'Home',
component: Home,
children: [
{
path: '/',
component: r => require.ensure([], () => r(require('@/views/Index')), 'index')
},
/*文章分类、标签*/
{
path: '/:type/all',
component: r => require.ensure([], () => r(require('@/views/categoryTagList/BlogAllCategoryTag')), 'BlogAllCategoryTag')
}
],
}
]
});
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}
export default router
分类详情、标签详情:
需要在BlogAllCategoryTag.vue设置view函数,使得点击每个标签跳转之后,路由能够对应传参id
view(id)
{
this.$router.push({path:`/${this.activeName}/${id}`});
},
需要新添加路由:
/*分类详情、标签详情*/
{
path: '/:type/:id',
component: r => require.ensure([], () => r(require('@/views/categoryTagDetail/BlogCategoryTagDetail')), 'BlogCategoryTag')
}
BlogCategoryTagDetail:
query是传给首页的ArticleScrollPage组件的参数,如果query有值tagId或者categoryId,就会传给ArticleScrollPage
ArticleScrollPage中的pageParams参数传给后端,如果有值tagId或者categoryId,后端的mybatisPlus就会把该条件加上,从而获得对应标签或者分类的文章列表,如果tagId或者categoryId为Null,就会查询所有文章列表。
并且对应的articlesNumber,后端也需要加上(与上一章节对应)
<template>
<div class="my-ct-body" v-title :data-title="title">
<el-container class="my-ct-container">
<el-main>
<div class="my-ct-title me-area">
<!--标签-->
<template v-if="this.$route.params.type === 'tag'">
<img class="my-ct-picture" :src="ct.avatar?ct.avatar:defaultAvatar"/>
<h3 class="my-ct-name">{{ct.tagName}}</h3>
</template>
<!--种类-->
<template v-else>
<img class="my-ct-picture" :src="ct.avatar?ct.avatar:defaultAvatar"/>
<h3 class="my-ct-name">{{ct.categoryName}}</h3>
<p>{{ct.description}}</p>
</template>
<!--对应的文章数量-->
<span class="my-ct-meta">{{ct.articlesNumber}} 篇文章</span>
</div>
<!--分页组件-->
<div class="my-ct-articles">
<article-scroll-page :query="query"></article-scroll-page>
</div>
</el-main>
</el-container>
</div>
</template>
<script>
import defaultAvatar from '@/assets/img/logo.png'
import ArticleScrollPage from "@/components/common/ArticleScrollPage"
import {getTagDetailById} from "@/api/tag"
import {getCategoryDetailById} from "@/api/category"
export default
{
name: "BlogCategoryTagDetail",
data(){
return {
defaultAvatar: defaultAvatar,
ct : {},
query : {
tagId:null,
categoryId:null
}
}
},
created(){
//进行后端请求 请求数据
this.getCategoryOrTagAndArticles();
},
methods:{
/*请求分类详情或者标签详情数据*/
getCategoryOrTagAndArticles()
{
let type = this.$route.params.type;
let id = this.$route.params.id;
if('tag' === type){
this.getTagDetailById(id);
this.query.tagId = id;
}
if('category' === type){
this.getCategoryDetailById(id);
this.query.categoryId = id;
}
},
getTagDetailById(id)
{
//发起http请求 请求标签详情
getTagDetailById(id).then((res)=>{
res.data = Result (success,msg,data)
if(res.data.success){
this.ct = res.data.data;
}else{
this.$message.error(res.data.msg);
}
}).catch((err)=>{
this.$message.error("系统错误");
}).finally(()=>{
})
},
getCategoryDetailById(id)
{
//发起http请求 请求分类详情
getCategoryDetailById(id).then((res)=>{
res.data = Result (success,msg,data)
if(res.data.success){
this.ct = res.data.data;
}else{
this.$message.error(res.data.msg);
}
}).catch((err)=>{
this.$message.error("系统错误");
}).finally(()=>{
})
}
},
computed:{
title(){
if(this.$route.params.type === 'tag'){
return "标签详情"
}else{
return "文章分类详情"
}
}
},
components:{
"article-scroll-page": ArticleScrollPage
}
}
</script>
<style>
.my-ct-body {
margin: 60px auto 140px;
min-width: 100%;
}
.el-main {
padding: 0;
}
.my-ct-title {
text-align: center;
height: 150px;
padding: 20px;
}
.my-ct-picture {
width: 60px;
height: 60px;
}
.my-ct-name {
font-size: 28px;
}
.my-ct-meta {
font-size: 12px;
color: #969696;
}
.my-ct-articles {
width: 640px;
margin: 30px auto;
}
</style>
ArticleScrollPage需要通过props获取BlogCategoryTagDetail,并且要设置一个默认值为空对象。如果不设置,则首页的ArticleScrollPage获取不到props,就会报错。
<template>
<scroll-page :loading="loading"
:offset="offset"
:no-data="noData"
@load="load">
<article-item v-for="article in articles"
:key="article.id"
v-bind="article">
</article-item>
</scroll-page>
</template>
<script>
import ArticleItem from '@/components/article/ArticleItem'
import ScrollPage from '@/components/scrollpage'
/*
引入文件时,../以该目录为基准,往上跳一个目录,ArticleScrollPage.vue目录为common,往上跳一个目录为components,需要再往上跳到src才能引入api
*/
import {getArticles} from '@/api/article'
export default
{
name: "ArticleScrollPage",
props: {
offset: {
type: Number,
default: 0
},
query: {
type:Object,
default()
{
return{}
},
}
},
created()
{
this.getArticles();
},
data() {
return {
loading: false,
noData: true,
//分页参数
PageParams: {
page: 1,
pageSize: 5,
tagId:null,
categoryId:null
},
//文章列表
articles: []
}
},
methods: {
load() {
//下拉触发分页的时候,调用接口加载
this.getArticles();
},
getArticles() {
let that = this;
that.loading = true;
this.PageParams.tagId = this.query.tagId;
this.PageParams.categoryId = this.query.categoryId;
getArticles(this.PageParams).then((res)=>
{
if(res.data.success)
{
if(res.data.data.length <= 0)
{
this.noData = true;
}
this.articles = this.articles.concat(res.data.data)
this.PageParams.page += 1;
}else
{
this.$message.error(res.data.msg)
}
}).catch((err)=>
{
console.log()
}).finally(()=>
{
that.loading = false
});
this.noData = false;
}
},
components: {
'article-item': ArticleItem,
'scroll-page': ScrollPage
}
}
</script>
<style scoped>
.el-card
{
border-radius: 6px;
}
.el-card:not(:first-child)
{
margin-top: 10px;
}
</style>