基于SpringBoot + Vue的个人博客系统06——前端环境搭建

1、使用 vue-cli 创建项目,并且安装依赖

vue-cli文档: https://cli.vuejs.org/zh/

说明:

  • 博客样式仿照 reco ,官网:https://vuepress-theme-reco.recoluan.com/,reco 是基于 VuePress 的一个静态博客,如果只是想搭建静态博客的话 reco 可以是一个好的选择,托管到 gitee page 或者 github page 上都很方便。

使用 npm install XXX 命令安装如下依赖:

  // package.json
  "dependencies": {
    "axios": "^0.19.2",
    "core-js": "^3.6.5",
    "element-ui": "^2.13.2",
    "vue": "^2.6.11",
    "vue-router": "^3.3.4",
    "vuex": "^3.5.1"
  },

说明:

  • axios 文档:https://www.kancloud.cn/yunye/axios/234845
  • element-ui 文档:https://element.eleme.cn/#/zh-CN/component/installation
  • vuex 文档:https://vuex.vuejs.org/zh/
  • vue-router 文档:https://router.vuejs.org/zh/
  • vue 文档:https://cn.vuejs.org/v2/guide/

2、开始搭建项目骨架,目录树如下:

E:\User\Desktop\qblog-client
λ tree /f
卷 个人文件 的文件夹 PATH 列表
卷序列号为 000C-C313
E:.
│  .gitignore
│  babel.config.js
│  package-lock.json
│  package.json
│  README.md
│  vue.config.js # vue-cli 配置文件
│
├─public
│      favicon.ico # 网站图标
│      index.html # 网站页面
│
└─src
    │  App.vue 
    │  main.js
    │
    ├─assets # 静态资源
    │      logo.png
    │
    ├─components # 自定义组件
    │      NavMenu.vue
    │
    ├─http # 发送请求相关
    │      request.js
    │      urls.js
    │
    ├─router # 路由
    │      index.js
    │
    ├─store # 全局状态管理(Vuex)
    │      index.js
    │
    └─views # 页面
            Category.vue
            Home.vue
            Message.vue
            Tag.vue
            TimeLine.vue

准备

先是在index.html中清除内外边距

<style>
  * {
    margin: 0;
    padding: 0;
  }
style>

跨域

首先是新建vue.config.js文件,配置代理,解决跨域问题

module.exports = {
  devServer: {
    proxy: {
      "/api": {
        target: "http://localhost:9000/api/",
        pathRewrite: {
          "^/api": ""
        }
      }
    }
  }
}

说明:

  • 跨域问题可以在前端项目中配置代理解决,也可以通过配置后端项目解决,选择一种方式即可,因为以后部署项目的时候准备使用 nginx 反向代理,所以这里使用vue-cli的提供的解决方法
  • 详细了解跨域可参考:http://www.ruanyifeng.com/blog/2016/04/cors.html

页面

@/views/文件夹下,新建主页面Home.vue






新建其他几个页面:

Category.vue:分类页面






Message.vue:留言页面






Tag.vue:标签页面






TimeLine.vue:时间线页面






路由

新建@/router/index.js使用vue-router组件做路由

import VueRouter from "vue-router";
import Vue from 'vue';

Vue.use(VueRouter);

const routes = [
  {
    path: "/",
    name: "Home",
    component: () => import("@/views/Home.vue"),
    meta: {
      title: "竹林客栈",
    },
  },
  {
    path: "/category/:name",
    name: "Category",
    component: () => import("@/views/Category.vue"),
    meta: {
      title: "文章分类",
    },
  },
  {
    path: "/tag/:name",
    name: "Tag",
    component: () => import("@/views/Tag.vue"),
    meta: {
      title: "标签",
    },
  },
  {
    path: "/timeline",
    name: "TimeLine",
    component: () => import("@/views/TimeLine.vue"),
    meta: {
      title: "时间线",
    },
  },
  {
    path: "/message",
    name: "Message",
    component: () => import("@/views/Message.vue"),
    meta: {
      title: "留言板",
    },
  },
]

const router = new VueRouter({
  mode: "history",
  routes
})

router.beforeEach((to, from, next) => {
  console.log(from);
  if (to.meta.title) {
    document.title = to.meta.title;
  }
  next();
});

export default router;

说明:

  • mode: “history”,表示路由使用history模式,即路由直接拼接在URL后面,而不是#的形式
  • beforeEach:此函数在路由跳跃之前执行,可用于权限管理,这里只是改变一下文档标题

全局状态管理

新建@/store/index.js,用于设置和存储全局状态

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

Vue.use(Vuex);

const store = new Vuex.Store({
  state: {
    token: window.sessionStorage.getItem("token"),
    userInfo: 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;
    },
  },
  actions: {}
});

export default store;

说明:

  • 因为以后可能会实现登录功能,所以全局状态里面放两个值:token 和 用户信息
  • 存储在浏览器的 sessionStorage 中的数据不会因为浏览器的刷新而消失,所以这里选择将 token 存入 sessionStorage 中

网络请求

新建@/http/urls.js用于存放请求地址

export default {
  baseUrl: "/api/v1",
  article: "/article",
  articles: "/articles"
}

新建@/http/request.js用于封装前端请求

import axios from 'axios'
import urls from "@/http/urls"
import store from "@/store/index"
import router from "@/router/index"

const instance = axios.create({
  baseURL: urls.baseUrl,
  timeout: 5000,
});

instance.interceptors.request.use((config) => {
  if (store.state.token) {
    config.headers.Authorization = store.state.token;
  }
  return config;
});

instance.interceptors.response.use(
  (response) => {
    return response;
  },
  (error) => {
    //默认除了2XX之外的都是错误的,就会走这里
    if (error.response) {
      switch (error.response.status) {
        case 401:
          router.replace({
            path: "login",
            query: { redirect: router.currentRoute.fullPath }, // 将跳转的路由path作为参数,登录成功后跳转到该路由
          });
      }
    }
    return Promise.reject(error.response);
  }
);

export default {
  getArticles(page, limit) {
    return instance.get(urls.articles, {
      params: {
        page: page,
        limit: limit
      }
    }).then(res => res.data); // 这里的 res => res.data 是为了防止axios中的data属性和返回值中的data属性混淆
  }
}

说明:

  • 请求拦截器主要是判断 store 是否含有 token ,如果有的话就加在请求头上
  • 响应拦截器,主要用于过滤错误的响应,这里只设置了对未登录状态码的拦截

入口文件

main.js中使用 Element-UI ,并且注册 storerouter

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';

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

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

新建@/components/NavMenu.vue组件,封装导航栏






说明:

  • el-menu 必须设置 router 才能开启路由功能,mode 属性用来表示导航栏是水平导航栏还是竖直导航栏

App.vue中使用导航栏

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

<script>
export default {
  name: "App",
  data() {
    return {};
  },
  components: {
    NavMenu: () => import("@/components/NavMenu.vue")
  }
};
script>

<style>
.main-text {
  text-decoration: none;
  color: #303133;
}
.comm-text {
  text-decoration: none;
  color: #606266;
}
.secondary-text {
  text-decoration: none;
  color: #909399;
  font-size: 13px;
}
.space-text {
  text-decoration: none;
  color: #c0c4cc;
  font-size: 13px;
}
.link {
  text-decoration: none;
}
.link:hover {
  cursor: pointer;
  color: #409eff;
}
style>

说明:

  • App.vue 中的 style 没有加 scoped 域,这里可以用来写一些全局样式。当然,也可以单独抽取一个 CSS 文件,这里为了简单就直接在里面写了。

效果

主界面:

基于SpringBoot + Vue的个人博客系统06——前端环境搭建_第1张图片

点击导航栏可以跳转到其他页面

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

你可能感兴趣的:(基于SpringBoot,+,Vue的个人博客系统,java,spring,boot,vue)