21.blog前端-分类详情、标签详情

本文讲述了如何修复Vue项目中点击文章分类或标签时路由不正确的问题,重点在于调整`activeName`的set方法以实现路由跟随,并添加新的分类详情和标签详情路由。同时介绍了BlogCategoryTagDetail组件的视图函数和ArticleScrollPage组件的交互。
摘要由CSDN通过智能技术生成

首先要解决一个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>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值