摘要
我一直觉得vue特别难入门,其实不是vue的语法难学,而是vue所附加的其他生态链让人头疼。
由此记录。
正文
实战项目可参考meethigher/code2word: Code2Word - 让高亮的代码完美呈现至 Word
一、Node版本管理
1.1 搭建node
1.1.1 Windows
准备nvm-windows,是windows系统用来管理node版本的工具。使用过node的应该都知道,node新版本是完全不兼容旧版本的,这就是这个工具存在的意义
1
2
3
4
5
6
7
8
9
| # 查看列表
nvm list
# 下载 16.16.0
nvm install 16.16.0
# 切换版本
nvm use 16.16.0
# 查看版本
node -v
npm -v
|
操作如图
1.1.2 Linux
保证配置代理的基础上,执行如下命令
1
2
3
4
5
6
7
| curl -L -o a.tar.gz https://github.com/nvm-sh/nvm/archive/refs/tags/v0.39.2.tar.gz && tar -zxvf a.tar.gz && mv nvm-0.39.2/ /usr/local/nvm
cat > /etc/profile.d/nvm.sh <<EOF
#!/usr/bin/env bash
export NVM_DIR="/usr/local/nvm"
[ -s "\$NVM_DIR/nvm.sh" ] && \. "\$NVM_DIR/nvm.sh" # This loads nvm
EOF
source /etc/profile && nvm --version
|
操作如图
参考CentOS7下安装NVM_centos 安装nvm_veejaLiu的博客-CSDN博客
1.2 创建vue项目
参考文档简介 | Vue.js,执行命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| C:\Users\meethigher\Desktop>npm init vue@3.4
npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.
Vue.js - The Progressive JavaScript Framework
√ Project name: ... vue-admin
√ Add TypeScript? ... No
√ Add JSX Support? ... No
√ Add Vue Router for Single Page Application development? ... Yes
√ Add Pinia for state management? ... No
√ Add Vitest for Unit Testing? ... No
√ Add an End-to-End Testing Solution? » No
√ Add ESLint for code quality? ... No
Scaffolding project in C:\Users\meethigher\Desktop\vue-admin...
Done. Now run:
cd vue-admin
npm install
npm run dev
|
按提示命令,启动项目
二、项目理解
2.1 配置IDE
作为一个后端人员来说,还是更喜欢jetbrains家的产品,此处使用的webstorm。由于写js习惯性带;,习惯用"",所以需要配置自动添加分号。
进行ctrl+alt+L格式化代码时,即可自动添加。
2.2 理解代码
1.) 理解main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| // 解构出 createApp
import {createApp} from "vue";
// 导入根组件
import App from "./App.vue";
// 导入路由配置
import router from "./router";
// 导入全局样式
import "./assets/main.css";
// 创建一个根app实例
const app = createApp(App);
// 将路由挂载到app实例
app.use(router);
// 将app实例挂载到id为app的元素上
app.mount("#app");
|
2.) 理解router.js,参考文档介绍 | Vue Router
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
| /*
* 1. 先导入 vue-router
* createRouter 创建路由的方法
* createWebHistory 路由模式(History) 前面用的是 / 开头,一般是要后端配合使用,容易产生404
* createWebHashHistory 路由模式(Hash) 前面用的是 # 开头,无需配合
* */
import {createRouter, createWebHistory, createWebHashHistory} from "vue-router";
// 导入home组件
import HomeView from "../views/HomeView.vue";
// 配置路由规则
const routers = [
{
//访问时的路径
path: "/",
//命名路由,路由的别名
name: "home",
//当访问到对应路由后需要展示的组件
//路由的急加载
component: HomeView
},
{
path: "/about",
name: "about",
//路由的懒加载,对于一些不确定立即需要显示的页面,可以使用懒加载
component: () => import("../views/AboutView.vue")
}
];
// 创建router
const router = createRouter({
// 配置路由模式
history: createWebHistory(import.meta.env.BASE_URL),
// 配置路由规则
routes: routers
});
// 导出路由
export default router;
|
3.) 理解app.vue
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
| <!--
在script标签中,带setup,说明在该script中写的所有代码,就是在setup中写的
-->
<script setup>
import {RouterLink, RouterView} from "vue-router";
//在setup中,不需要手动注册组件,直接导入即可使用
import HelloWorld from "./components/HelloWorld.vue";
</script>
<template>
<header>
<div class="wrapper">
<HelloWorld msg="You did it!"/>
<nav>
<!--RouterLink表示声明式跳转-->
<!--还有编程式跳转 通过js跳转-->
<!--to属性指定需要跳转的路径-->
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/about">About</RouterLink>
</nav>
</div>
</header>
<!--RouterView:路由出口,所有的组件页面,都可以通过RouterView来展示-->
<RouterView/>
</template>
<!--
scoped该属性是用来标记当前样式只能在当前组件中使用
其存在的目的是为了防止样式冲突
-->
<style scoped>
header {
line-height: 1.5;
max-height: 100vh;
}
.logo {
display: block;
margin: 0 auto 2rem;
}
nav {
width: 100%;
font-size: 12px;
text-align: center;
margin-top: 2rem;
}
nav a.router-link-exact-active {
color: var(--color-text);
}
nav a.router-link-exact-active:hover {
background-color: transparent;
}
nav a {
display: inline-block;
padding: 0 1rem;
border-left: 1px solid var(--color-border);
}
nav a:first-of-type {
border: 0;
}
@media (min-width: 1024px) {
header {
display: flex;
place-items: center;
padding-right: calc(var(--section-gap) / 2);
}
.logo {
margin: 0 2rem 0 0;
}
header .wrapper {
display: flex;
place-items: flex-start;
flex-wrap: wrap;
}
nav {
text-align: left;
margin-left: -1rem;
font-size: 1rem;
padding: 1rem 0;
margin-top: 1rem;
}
}
</style>
|
三、搭建项目
3.1 置空项目
将不必要的文件都删除,最后的结构如图
启动项目后是个空的
3.2 安装css预编译less
安装
1
2
| # 带上-D参数,表示安装到devDepencencies
npm install less
|
使用
1
2
3
4
| <!--css预编译语言:less、sass-->
<!--webstorm不支持sass的代码提示,刚好我也不会-->
<style scoped lang="less">
</style>
|
3.3 安装全局初始化样式
normalize - npm
安装
在main.js中全局引用
1
2
| // 导入全局格式化标签样式
import "normalize.css/normalize.css";
|
3.4 安装element-plus
在element-plus中,元素名恰好是对应的class名称,可以直接配样式
快速开始 | Element Plus
安装
1
| npm install element-plus
|
配置自动按需导入
1
| npm install -D unplugin-vue-components unplugin-auto-import
|
按照官网要求修改vite.config.js
3.5 安装element-icon
Icon 图标 | Element Plus安装
1
| npm install @element-plus/icons-vue
|
实际使用时,手动按需引入即可,如下
1
| import {Fold, Expand} from "@element-plus/icons-vue";
|
3.6 安装axios
3.6.1 配置axios
Axios安装
封装通用request.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
74
75
76
77
| import axios from "axios";
//封装baseUrl
//开发环境development 打包命令npm run dev
//生产环境production 打包命令npm run build
const isDev = process.env.NODE_ENV == "development";
const dev = "http://127.0.0.1/api/";
const pro = "http://121.89.205.189:3000/";
const request = axios.create({
baseURL: isDev ? dev : pro,
timeout: 60000,//单位毫秒
headers: {"X-Custom-Header": "foobar"}
});
// 添加请求拦截器
request.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
request.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
return response;
}, function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
return Promise.reject(error);
});
// 自定义各种数据请求
export default function ajax(config) {
//解构赋值 https://www.cnblogs.com/tfxz/p/12838739.html
// let node = {
// type: "Identifier"
// };
// // 使用解构来创建两个字段,type、name,如果node中该字段有值,则覆盖掉
// ({type = 'type', name = 'name'} = node);
// console.log(type); // "Identifier"
// console.log(name); // "name"
const {url = "", method = "GET", data = {}, headers = {}} = config;
//判断请求类型
switch (method.toUpperCase()) {
case "GET":
return request.get(url, {
params: data
});
case "POST":
//表单形式
if (headers["content-type"] == "application/x-www-form-url-encoded") {
//格式化数据
const obj = new URLSearchParams();
for (let key in data) {
obj.append(key, data[key]);
}
return request.post(url, data, {headers});
}
//文件形式
if (headers["content-type"] == "multipart/form-data") {
//文件处理对象
let obj = new FormData();
for (let key in data) {
obj.append(key, data[key]);
}
return request.post(url, data, {headers});
}
//json形式
return request.post(url, data);
}
}
|
3.6.2 配置vite跨域
开发服务器选项 | Vite 官方中文文档
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| server: {
port: 80,
open: false, //自动打开
base: "./ ", //生产环境路径
/*配置代理转发,开发环境使用https://www.cnblogs.com/tik2012/p/16866356.html*/
proxy: { // 本地开发环境通过代理实现跨域,生产环境使用 nginx 转发
// 正则表达式写法
'^/api': {
target: 'http://121.89.205.189:3000/', // 后端服务实际地址
changeOrigin: true, //开启代理
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
|
3.7 安装全局数据管理工具
可选框架,两者二选一即可
在vue2.x中推荐使用vuex,在vue3.x中推荐使用pinia。pinia相比vuex使用起来更简洁。
3.7.1 vuex
配置vuex
Vuex 是什么? | Vuex安装
封装通用vuex.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
| // 使用vuex进行全局状态管理
import {createStore} from "vuex";
const store = createStore({
//严格模式,在生产环境中,不能打开
strict: process.env.NODE_ENV !== "production",
//全局状态
state() {
return {
count: 100,
//用户信息
userInfo: {}
};
},
//项目中唯一修改数据的方法
//严格模式中,不允许在这里做异步,要在actions里面做。比如setTimeout等
mutations: {
add(state) {
state.count++;
},
addNum(state, amount) {
state.count += amount;
},
//保存用户数据
updateUserInfo(state, value) {
state.userInfo = value;
}
},
//异步修改数据的地方
actions: {
addAction(context) {
setTimeout(function () {
/*所谓异步,也还要调用同步的方法进行修改数据*/
context.commit("add");
}, 5000);
},
addActionNum(context, amount) {
setTimeout(function () {
/*所谓异步,也还要调用同步的方法进行修改数据*/
context.commit("addNum", amount);
}, 5000);
}
},
//vuex中的计算属性
getters: {},
//全局状态模块
modules: {}
});
//导出创建好的实例
export default store;
|
vuex数据持久化
持久化vuex数据,方便在页面重新加载时,恢复数据。
- 通过自己手动存储需要持久化的数据
- 通过插件进行自动持久化
自动持久化,需要安装vuex插件
1
| npm install vuex-persistedstate
|
添加plugins,如下图
使用生命周期函数验证登录
1
2
3
4
5
6
7
8
9
10
| export default {
//生命周期函数
mounted() {
//用户没有登录
if (!this.$store.state.userInfo.adminname) {
this.$router.push("/login");
return;
}
}
}
|
3.7.2 pinia
Vue3项目中推荐使用Pinia,安装
在main.js注册pinia
1
2
3
4
5
6
7
8
9
10
| // src/main.js
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
const app = createApp(App);
const pinia = createPinia();
app.use(pinia);
app.mount('#app');
|
创建Pinia Store
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| // src/stores/codeStore.js
import {defineStore} from 'pinia'
export const useCodeStore = defineStore('code', {
state: () => ({
detectedLanguage: '未识别',
rawCode: '', // 原始代码(输入区)
emitCode:'', // 高亮按钮传递的数据
highlightedCode: '', // 高亮后的代码(预览区)
outside: false // 序号是否展示在外侧。word只支持内侧
}),
actions: {
// 更新输入的代码
setRawCode(code) {
this.rawCode = code
},
// 更新高亮代码(这里可以集成 highlight.js 进行高亮处理)
setHighlightCode(code) {
this.highlightedCode = code;
}
}
})
|
在组件中使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| <template>
<nav class="navbar">
<div class="nav-links">
<a :href="Utils.home" class="link">主页</a>
<a :href="Utils.blog" class="link">博客</a>
<a :href="Utils.github" target="_blank" class="link">GitHub</a>
</div>
</nav>
</template>
<script setup>
import {Utils} from "./utils/utils";
import logo from "@/assets/logo.svg";
Utils.printProjectInfo();
Utils.printAttention();
</script>
|