言成言成啊 | Kit Chen's Blog

创建Vue3+Vite单页面应用总结

2023-01-02 00:16:12 转载随意,文章会持续修订,请注明来源地址:https://meethigher.top/blog

一、Node版本管理

1.1 搭建node

准备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.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@latest
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

安装

1
npm install normalize

在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

配置axios

Axios安装

1
npm install 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);
}
}

配置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 安装vuex

配置vuex

Vuex 是什么? | Vuex安装

1
npm install vuex@next

封装通用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数据,方便在页面重新加载时,恢复数据。

  1. 通过自己手动存储需要持久化的数据
  2. 通过插件进行自动持久化

自动持久化,需要安装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;
}
}
}
发布:2023-01-02 00:16:12
修改:2023-01-28 21:22:31
链接:https://meethigher.top/blog/2023/my-vue3-stack/
标签:web 
付款码 打赏 分享
shift+ctrl+1可控制目录显示