基于SpringBoot + Vue的个人博客系统08——博客信息部分

简介

博客信息部分主要放在文章列表的右边,主要包含三个部分:1、个人信息,2、分类列表,3、标签列表

代码实现

因为博客信息在多个组件中用得到,所以可以将其存入 vuex 中, vuex 文档:https://vuex.vuejs.org/zh/

先在 @/http/urls.js中新增url地址

export default {
  baseUrl: "/api/v1",
  article: "/article",
  articles: "/articles",
  tags: "/tags",
  tag: "/tag",
  categories: "/categories",
  category: "/category",
  info: "/info"
}

@/http/request.js中封装请求方法

  getAllTags() {
    return instance.get(urls.tags).then(res => res.data);
  },
  getAllCategories() {
    return instance.get(urls.categories).then(res => res.data);
  },
  getBlogInfo() {
    return instance.get(urls.info).then(res => res.data);
  }

在 store 中封装请求博客信息的方法

import Vue from 'vue';
import Vuex from 'vuex';
import request from '@/http/request';
import { Notification } from 'element-ui';

Vue.use(Vuex);

const store = new Vuex.Store({
  state: {
    token: window.sessionStorage.getItem("token"),
    userInfo: null,
    blogInfo: null
  },
  mutations: {
    setToken(state, token) {
      state.token = token;
      window.sessionStorage.setItem("token", token);
    },
    removeToken(state) {
      state.token = "";
      state.userInfo = null;
      window.sessionStorage.removeItem("token");
    },
    setUserInfo(state, userInfo) {
      state.userInfo = userInfo;
    },
    setBlogInfo(state, blogInfo) {
      state.blogInfo = blogInfo;
    },
  },
  actions: {
    getBlogInfo({ commit }) {
      request.getBlogInfo().then(res => {
        if (res.code === 0) {
          commit('setBlogInfo', res.data);
        } else {
          Notification.error({
            title: '提示',
            message: res.msg
          });
        }
      }).catch(err => {
        console.log(err);
        Notification.error({
          title: '提示',
          message: "服务器忙,获取博客信息失败"
        });
      })
    }
  }
});

export default store;

说明:

  • 这里单独导入 Notification 来实现消息提示的功能
  • vuex 中 Action 类似于 mutation,但是 Action 可以包含任意异步操作。

在 Vue 实例创建的时候调用 getBlogInfo函数

import Vue from 'vue'
import App from './App.vue'
import store from "@/store/index"
import router from "@/router/index"
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import 'github-markdown-css/github-markdown.css';
import 'highlight.js/styles/github.css'

Vue.config.productionTip = false
Vue.use(ElementUI);

import { VueShowdown } from 'vue-showdown'
Vue.component('VueShowdown', VueShowdown)

new Vue({
  render: h => h(App),
  store,
  router,
  created: initBlog
}).$mount('#app')

function initBlog() {
  store.dispatch('getBlogInfo');
}

然后我们就可以修改 Home.vue 了,改成从 vuex 中获取数据

<template>
  <div>
    <el-carousel indicator-position="none" height="400px" arrow="nerver" :interval="5000">
      <el-carousel-item v-for="item in blogInfo.covers" :key="item">
        <div class="item-box">
          <img :src="item" class="carimg" />
          <div class="desc-box">
            <h1>{{ blogInfo.title }}</h1>
            <p>{{ blogInfo.desc }}</p>
          </div>
        </div>
      </el-carousel-item>
    </el-carousel>
    <el-row :gutter="20">
      <!-- ......此处省略 -->
    </el-row>
  </div>
</template>

<script>
import request from "@/http/request";
import { mapState } from "vuex";

export default {
  name: "Home",
  data() {
    return {
      pageInfo: {}
    };
  },
  computed: mapState(["blogInfo"]),
  // ......此处省略
};
</script>

<style scoped>
// ......此处省略
</style>

博客信息组件的封装

新建 @/components/BlogInfo.vue 组件

HTML部分

<template>
  <el-card>
    <el-avatar :size="96" :src="blogInfo.avatar" fit="cover"></el-avatar>
    <div class="nickname">{{blogInfo.nickname}}</div>
    <div class="info-box">
      <div class="text-center">
        <div class="info-count">{{blogInfo.articleCount}}</div>
        <div class="info-desc">文章数</div>
      </div>
      <div class="text-center">
        <div class="info-count">{{blogInfo.totalViews}}</div>
        <div class="info-desc">浏览量</div>
      </div>
    </div>
    <el-divider></el-divider>
    <i class="el-icon-menu">文章分类</i>
    <router-link
      :to="'/category/' + category.name"
      class="category-item"
      v-for="(category,index) in categories"
      :key="index"
    >
      {{category.name}}
      <el-tag type="success" size="small" effect="dark">{{category.count}}</el-tag>
    </router-link>
    <el-divider></el-divider>
    <i class="el-icon-price-tag">文章标签</i>
    <div class="tag-box">
      <router-link :to="'/tag/' + tag" v-for="(tag,index) in tags" :key="index">
        <el-tag effect="plain" size="small">{{tag}}</el-tag>
      </router-link>
    </div>
  </el-card>
</template>

说明:

  • 分为个人信息、文章标签、文章分类三个面板
  • 每个面板之间使用 el-divider 分隔,此组件为ElementUI的分割线组件
  • 标签和分类分别使用 router-link 组件包裹,点击可跳转到对应路由

js 部分:

import request from "@/http/request";
import { mapState } from "vuex";

export default {
  name: "BlogInfo",
  data() {
    return {
      categories: [],
      tags: []
    };
  },
  computed: mapState(["blogInfo"]),
  created() {
    request
      .getAllTags()
      .then(res => {
        if (res.code === 0) {
          this.tags = res.data;
        } else {
          this.$notify.error({
            title: "提示",
            message: res.msg
          });
        }
      })
      .catch(err => {
        console.log(err);
        this.$notify.error({
          title: "提示",
          message: "网络忙,标签获取失败"
        });
      });
    request
      .getAllCategories()
      .then(res => {
        if (res.code === 0) {
          this.categories = res.data;
        } else {
          this.$notify.error({
            title: "提示",
            message: res.msg
          });
        }
      })
      .catch(err => {
        console.log(err);
        this.$notify.error({
          title: "提示",
          message: "网络忙,文章分类获取失败"
        });
      });
  }
};

说明:

  • 在 created 方法中获取分类和标签
  • 从 vuex 中取博客信息

css部分:

.el-avatar {
  display: block;
  margin: 0 auto;
}
.nickname {
  margin-top: 5px;
  color: #303133;
  font-size: 16px;
  text-align: center;
}
.info-box {
  margin-top: 10px;
  display: flex;
  justify-content: space-around;
  align-items: center;
}
.info-count {
  color: #303133;
  font-weight: bold;
  font-size: 20px;
}
.info-desc {
  color: #909399;
  font-size: 12px;
}
.category-item {
  display: block;
  text-decoration: none;
  font-size: 14px;
  color: #606266;
  margin-top: 10px;
  padding: 8px;
  transition: all 0.5s;
  border-radius: 5px;
  border: 1px solid #ebeef5;
}
.category-item:hover {
  box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 8px 0px;
  cursor: pointer;
  transform: scale(1.03);
  color: #303133;
}
.category-item .el-tag {
  float: right;
}
.tag-box {
  margin-top: 10px;
}
.tag-box .el-tag {
  margin: 0 2px;
}
.tag-box .el-tag:hover {
  background-color: #409eff;
  color: #ffffff;
  cursor: pointer;
}

说明:

  • 基本都是一些常见 CSS 属性,主要说一下 transform: scale(1.03); 为方法效果,scale() 的参数为放大倍数。这里的效果是鼠标移动到指定分类的时候,该分类有放大效果
  • 另外使用到了 flex 布局,详情可参考:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

然后在主界面博客信息的地方引入该组件就行了。

页面效果:

博客信息页面展示

参考代码:https://gitee.com/qianyucc/QBlog2/tree/v-6.0

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值