基于 GitHub Pages + Hexo 搭建个人博客

环境准备

1. 安装node.js

文字 或者 markdown 均可

下载地址:https://nodejs.org/en/

2. 检查安装

image-20220917170738464

搭建vue环境

1. 全局安装脚手架vue-cli

在命令行输入:

vue-cli2(第一行)

vue-cli3(第二行)

1
2
npm install vue-cli -g
npm install -g @vue/cli

2. 检查是否安装成功:输出版本号说明安装成功

1
vue --version

创建vue项目的三种方法

1. webpack创建项目

  • 以管理员打开命令行界面

  • 全局安装webpack(vue2需要安装这个)

    1
    npm install webpack -g
  • 创建项目(blog)

    1
    vue init webpack blog

    image-20220917172235775

  • 输入 npm run dev 运行项目

2. vue-cli3创建项目

  • 在需要创建项目的路径下进入cmd

  • 输入命令 vue create 项目名称

    image-20220917172536684

3. 基于图形化界面的方式创建vue

  • 主要依赖于vue-cli3,在全局安装完成cli3.0之后,在cmd输入vue ui启动

使用webpack与vue-cli3创建项目的区别

image-20220917172907851

  1. vue-cli3移除了配置文件目录:config和build文件夹,增加里vue.config.js文件,移除了static静态文件夹,新增public文件夹并将index.html移动到public中
  2. vue-cli2在config中的dev.env.js和prod.env.js中分别配置了域名,vue-cli3在vue.config中配置域名
  3. ==vue-cli2在config中的index.js中配置跨域,vue-cli3在vue.config.js中配置跨域。==
  4. vue-cli3内部封装了webpack且做了很多适合vue项目的优化,可以用vue.config.js来管理项目,vue-cli2更加适合含有特殊需求的,毕竟是原生的,但管理起来复杂,一般来说,vue-cli3够用了,但是vue-cli3能实现的,vue-cli2一定能实现,vue-cli2可以实现的,vue-cli3不一定能实现。

搭建vue项目开发环境

配置跨域

在对应的文件中配置信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module.exports = {
devServer: {
port: 9000,//端口号
host:'localhost',//指定主机地址 解决vue-cli5项目启动地址为0.0.0.0:端口号
open: true,
proxy: {
'/api': {
target: 'http://localhost:6020/imooc', // 目标接口域名
secure: false, // false为http访问,true为https访问
changeOrigin: true, // 是否跨域
pathRewrite: {
'^/api': '/' //将路径上的/api替换为/,并在/之前拼接target参数
}
}
}
// before: require('./mock/mock-server.js')
}
}

vuex

Vuex是一个专为VUe.js应用程序开发的状态管理模式+库,比如说全局变量的存取

1. 安装
1
npm install vuex@next --save
2. 在store文件夹创建index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import { createStore } from 'vuex'

export default createStore({
//存放数据的地方
state: {
//就是公共数据,所有组件都可以直接使用
sysUser:{},
dept:{},
showOverlay:false
},
//类似于computed,计算属性,派生数据(很少用)
getters: {
},
//使用它来修改数据(类似于methods)
mutations: {
setSysUser(state,newValue){
state.sysUser=newValue
},
setDept(state,newValue){
this.state.dept=newValue
},
setShowOverlay(state,newValue){
this.state.showOverlay=newValue
}
},
//发起异步请求
actions: {
},
//模块拆分
modules: {
}
})

3. 在页面如何使用
1
2
3
4
5
6
7
8
9
import { useStore } from "vuex"
export default{
setup() {
const store = useStore();
cosole.log(store.state.showOverlay)//获取全局变量
let that=this
that.$store.commit("setShowOverlay",true)//设置全局变量
}
}
4. 注意

上述方式(mutation)限制的是必须同步执行,可以通过Action方式去调用异步API和分发多重mutation(相当于在一个action中对多个mutation进行操作),所以这个需要后续补充。

vue-router

主要是实现vue项目的页面跳转,以及定义页面跳转之前的或者之后的公用方法,可以实现相当于一个拦截器类似的功能。

1. 安装(vue-router4)
1
npm install vue-router@4
2. 书写index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import { createRouter, createWebHistory } from 'vue-router'
import LoginView from '../views/LoginView.vue'

const routes = [
{
path: '/',
name: 'login',
component: LoginView
},
{
path: '/dashboard',
name: 'dashboard',
component: () => import(/* webpackChunkName: "about" */ '../views/DashboardView.vue')
},
{
path:'/user',
name: 'user',
component: ()=>import('../views/UserView')
},
{
path: '/register',
name: 'register',
component: ()=>import('../views/RegisterView')
}

]

const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
router.beforeEach((to, from, next) => {
//to到哪儿 from从哪儿离开 next跳转 为空就是放行
if (to.path === '/') {
//如果跳转为登录,就放行
next();
} else {
//取出localStorage判断
let token = localStorage.getItem('token');
if (token == null || token === '') {
console.log('请先登录')
next({
path: '/',
query: {
redirect: to.fullPath
} // 将跳转的路由path作为参数,登录成功后跳转到该路由
})
} else {
next();
}
}});

export default router

3. 主体页面如何引用组件页面
  • 主体vue页面

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <template>
    <HistoryPurchaseView></HistoryPurchaseView>
    </template>
    <script>
    import { HistoryPurchaseView } from '../components'
    export default{
    components:{
    HistoryPurchaseView
    }
    }
    </script>
  • components文件夹中index.js暴露组件页面

    如果是需要暴露多个组件页面的话,直接往下就添加既可,格式和第一个一样,改个组件名和文件路径

    1
    export{default as HistoryPurchaseView} from './HistoryPurchaseView'
4. 在vue3中如何定义数据和方法

==主要是在setup()方法中设置,该方法中的生命周期在created()之前,所以在这个方法中this是未定义的==

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<template>
</template>
<script>
import { ref } from 'vue';
export default{
setup(){
const isActive=ref(false)//布尔类型
const typeSelect=ref(0)//int类型
const timeTitle =ref('')//字符串类型
const currentDate=ref(new Date())
const item=ref(null)//对象
const option=[
{text:'历史数据',value:0},
{text;'排行数据',value:1}
];
//以下几种定义方法
const onConfirmEndTime = (value) =>{
//业务处理 比如设置值
timeTitle.value='第一个';
}
function getAllData(param){

}
}
return{
isActive,
typeSelect,
timeTitle,
currentDate,
item,
option,
onConfirmEndTime,
getAllData
};
}
</script>
5. 页面传参(typeSelect、timeTile、startTimeResult、endTimeResult)

应该还有其他方式的传参,这里只写现在用的,其他的也不知道

1
2
3
4
5
6
7
8
9
10
11
<template>
<HistoryPurchaseView :typeSelect="typeSelect" :timeSelect="timeTitle" :timeStart="startTimeResult" :timeEnd="endTimeResult"></HistoryPurchaseView>
</template>
<script>
import { HistoryPurchaseView } from '../components'
export default{
components:{
HistoryPurchaseView
}
}
</script>

跳转的页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
</template>
<script>
export default{
name:'HistoryPurchaseView',
props:{
typeSelect:String,//定义传值的类型
timeSelect:String,
},
watch:{
'timeSelect'(newVal,oldVal){
//监听timeSelect的变化执行对应的方法
}
}
}
</script>

axios

axios是一个强大的发送http请求的库,通过我们的二次封装可以大大提高我们的开发效率。

http.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import axios from 'axios'
import store from './src/store/index'
axios.defaults.timeout = 5000; //响应时间
//axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8'; //配置请求头
axios.defaults.baseURL = ''; //配置接口地址

//POST传参序列化(添加请求拦截器)
axios.interceptors.request.use((config) => {
//在发送请求之前做某件事
/*if(config.method === 'post'){
config.data = qs.stringify(config.data);
}*/
if (config.push === '/') {
} else {
if (localStorage.getItem('token')) {
//在请求头加入token,名字要和后端接收请求头的token名字一样
config.headers.Authorization = localStorage.getItem('token');
}
}
return config;
},(error) =>{
console.log('错误的传参')
return Promise.reject(error);
});

//返回状态判断(添加响应拦截器)
axios.interceptors.response.use((res) =>{
//对响应数据做些事
if(!res.data.success){
//清除token
localStorage.removeItem('token');
return Promise.resolve(res);
}
//在返回状态的拦截器中设置不展示遮罩
store.state.showOverlay=false
return res;
}, (error) => {
console.log('网络异常')
return Promise.reject(error);
});

//返回一个Promise(发送post请求)
export function fetchPost(url, params) {
return new Promise((resolve, reject) => {
axios.post(url, params)
.then(response => {
resolve(response);
}, err => {
reject(err);
})
.catch((error) => {
reject(error)
})
})
}
////返回一个Promise(发送get请求)
export function fetchGet(url, param) {
return new Promise((resolve, reject) => {
axios.get(url, {params: param})
.then(response => {
resolve(response)
}, err => {
reject(err)
})
.catch((error) => {
reject(error)
})
})
}
export default {
fetchPost,
fetchGet,
}
具体使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import https from '../../http.js'
const onSubmit = (values) => {
https.fetchPost('api/security/token/login',values).then(function (res) {
if(res.data.success){
//设置登录成功返回的token
let token = res.data.data.access_token;
window.localStorage.setItem("token", token);
router.push('/dashboard')
}else{
Toast(res.data.message)
}
}).catch(function(err){
Toast("登录请求失败!!!");
})
};

qs

qs 是一个增加了一些安全性的查询字符串解析和序列化字符串的库。

安装
1
npm install qs
应用
1
import qs from 'qs'

qs.parse()是将URL解析成对象的形式
qs.stringify()是将对象序列化成URL的形式,以&进行拼接

项目上一些问题解决

组件上动态的让class是否生效

1
2
3
4
5
6
7
8
9
10
11
<div :class={myClass:isActive}>

</div>
<script>
//这里动态的修改isActive的值,为true这myClass生效,为false则不生效
</script>
<style>
.myClass{
height:100xp;
}
</style>

页面刷新导致本页面的数据为初始值,导致查询方法数据失败

在app.vue中添加一下代码,还有通过全局变量控制遮罩是否在加载前显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<van-overlay :show="$store.state.showOverlay">
<div class="wrapper" @click.stop>
<van-loading size="40px" type="spinner" vertical >加载中...</van-loading>
</div>
</van-overlay>
<router-view/>
</template>
<script>
export default {
created() {
//在页面刷新时将vuex里的信息保存到localStorage里
window.addEventListener("beforeunload",()=>{
console.log("页面刷新了........")
localStorage.setItem("sysUser",$store.state.sysUser);
localStorage.setItem("sysDept",$store.state.dept);
})
}
}
</script>

基于 GitHub Pages + Hexo 搭建个人博客
http://example.com/2022/10/16/my-blog-build-remark/
作者
zhuixun
发布于
2022年10月16日
许可协议