springboot+vue+elementUI搭建个人博客

duck blog 博客项目

  • 第一阶段----雏形
  • 1. vue前端
    • 1.1 全局文件说明
    • 1.2 登录功能
    • 1.3 注册功能
    • 1.4 博客列表
    • 1.5 博客编辑
    • 1.6 博客详情
    • 1.7 路由守卫
  • 2. springboot后端
  • 待完善内容
  • 第二阶段 优化完善+新功能

技术栈

  • SpringBoot
  • mybatis plus
  • shiro
  • lombok
  • redis
  • hibernate validatior
  • jwt

第一阶段----雏形

1. vue前端

1.1 全局文件说明

springboot+vue+elementUI搭建个人博客_第1张图片
所有页面注册路由的文件,router下index

import Vue from 'vue'
import Router from 'vue-router'
import Login from "../view/Login";
import Blogs from "../view/Blogs";
import Regist from "../view/Regist";
import BlogEdit from "../view/BlogEdit";
import BlogDetail from "../view/BlogDetail";
import Community from "../view/Community";

Vue.use(Router)


export default new Router({
  routes: [
    // 重定向
    {
      path: "/",
      redirect:'/login'

    },
    {
      path:"/blog_community",
      name:"BlogCommunity",
      component:Community
    },
    {
      path: "/login",
      name: "Login",
      component: Login
        },
    {
      path: "/regist",
      name: "Regist",
      component: Regist
    },
    {
      path:"/add",
      name:"Edit",
      meta:{
        requireAuth: true
      },
      component:BlogEdit
    },
    {
      path:"/blogs",
      name:"Home",
      meta:{
        requireAuth: true
      },
      component:Blogs
    },
    {
      path:"/blog_detail/:blogId",
      name:"BlogDetail",
      meta:{
        requireAuth: true
      },
      component:BlogDetail
    }
      ]
})

mainjs全局文件引入插件,自己写的js等

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI, {MessageBox} from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import axios from 'axios';
import less from 'less'
// 添加全局样式
import './assets/css/globle.css';
// 引入iconfront
import './assets/font/iconfont.css'
// 引入vuex-store
import store from './store/index';
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
//引入路由守卫
import './permission'

Vue.use(mavonEditor)
Vue.prototype.$confirm=MessageBox.confirm
Vue.use(less)
Vue.prototype.$axios = axios;
Vue.use(ElementUI);

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: ''
})

App.vue路由占位符,vue是单页面,router-view也就是每次加载页面替换的页面部分

<template>
  <div id="app">
    
    <router-view>router-view>
  div>
template>

<style>
  #app{

  }
style>

<script>
  export default {
  };
script>

store下index.js

啥是store?
Vuex就是提供一个仓库,Store仓库里面放了很多对象。其中state就是数据源存放地,对应于与一般Vue对象里面的data(后面讲到的actions和mutations对应于methods)。
在使用Vuex的时候通常会创建Store实例new Vuex.store({state,getters,mutations,actions})有很多子模块的时候还会使用到modules。

  • vuex优势:相比sessionStorage,存储数据更安全,sessionStorage可以在控制台被看到。

  • vuex劣势:在F5刷新页面后,vuex会重新更新state,所以,存储的数据会丢失。(后面因为这个踩坑)

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)


export default new Vuex.Store({
  //相当于私有属性
  state: {
    token: '',
    userInfo: ''
  },

  //相当于set方法
  mutations: {
    SET_TOKEN: (state, token) => {
      state.token = token
      localStorage.setItem("token", token)
    },
    SET_USERINFO: (state, userInfo) => {
      state.userInfo = userInfo
      sessionStorage.setItem("userInfo", JSON.stringify(userInfo))
    },
    REMOVE_INFO: (state) => {
      localStorage.setItem("token", '')
      sessionStorage.setItem("userInfo", JSON.stringify(''))
      state.userInfo = {}
    }
  },

  // 相当于get
  getters: {
    getUser: state => {
      return state.userInfo
    }
  },
  actions: {},
  modules: {}
})

公共组件
因为后面页面都需要一个头部信息,所以抽取出来做成组件,只要引用就可以了。

<template>
  <div class="m-content">
    <h3>欢迎来到{{user.username}}的博客h3>
    <div class="block">
      <el-avatar :size="50" :src="require('.././assets/css/img/user.jpg')" fit="cover">el-avatar>
      <div>{{ user.username }}div>
    div>
    <div>
    <el-divider direction="vertical">el-divider>
        <el-link class="el-icon-edit" @click="toAdd" type="primary">发表el-link>
    <el-divider direction="vertical">el-divider>
    <el-link class="el-icon-delete" type="danger" @click="toBlogs">主页el-link>
    <el-divider direction="vertical">el-divider>
    <el-link class="el-icon-switch-button" type="warning" v-show="hasLogin" @click="logout">退出el-link>
    <el-link class="el-icon-switch-button" type="warning" v-show="!hasLogin">请登录el-link>
    <el-divider direction="vertical">el-divider>
    div>
  div>
template>
<script>
    export default {
      name: "Header",
      data() {
        return {
          hasLogin: false,
          user: {
            username: '',
            avatar: "../assets/css/img/user.jpg"
          },
          blogs: {},
          currentPage: 1,
          total: 0
        }
      },
      methods: {
        logout() {
          const _this = this
            _this.$store.commit('REMOVE_INFO')
            _this.$router.push('/login')
        },
        toAdd() {
          this.$router.push({
            path:'/add',
          })
        },
        toBlogs(){
          this.$router.push({
            path:'/blogs',
          })
        }
      },
      // 从store中取出用户信息存到data中定义的变量user中
      created() {
        if(this.$store.getters.getUser.username) {
          this.user.username = this.$store.getters.getUser.username
          this.user.img = "../assets/css/img/user.jpg"
          this.hasLogin = true
        }
      }
    }
script>

<style scoped>
  .m-content{
    text-align: center;
  }
style>

引入方式