Vue3项目的搭建与使用
最后更新:2023-03-26
官方地址:Vue - 快速上手
前言
因前端各方面技术更新速度极快,网络上的各类教程可能都会使用不同的方式,其中大部分具有时效性,故决定写一篇时时更新的教程,并记录最新更新时间与所使用各项技术的版本,确保并不过时。
本文专注于Vue3+TypeScript+组合式API+常用组件的前端项目搭建,不涉及Git或VSCode之类相关工具的安装。
工具版本
git: 2.40.0.windows.1
node:14.18.0 | 18.15.0 | 19.8.1
vite: 4.2.1
vue-cli: 2.9.6
项目构建
一、使用Vite构建项目
开发环境下的性能比Vue cli要快10~100倍。
初始化项目
- 使用Git Bash或cmd或VSCode打开一处文件夹
- 执行指令
npm create vite@latest
- 接下来出现的选项,单选项可以通过方向键选择,或输入
Y
或N
进行是否选择,多选项通过空格选中,回车确认
- 接下来出现的选项,单选项可以通过方向键选择,或输入
- 若为初次使用,可能会提示
Need to install the following packages: create-vite@latest Ok to proceed? (y)
,需要安装create-vite包- 输入
y
,确认安装
- 输入
- 提示
Project name:
,输入项目名称 - 提示
Select a framework:
,选择一个前端框架- 选择
Vue
- 选择
- 提示
Select a variant:
,选择一种变体- 选择
Customize with create-vue
- 显示
Vue.js - The Progressive JavaScript Framework
标题,进入Vue的项目构建流程
- 显示
- 选择
- 提示
Add TypeScript?
,是否添加TypeScript- 选择
Yes
,使用TypeScript作为脚本语言
- 选择
- 提示
Add JSX Support?
,是否添加JSX支持- 选择
No
,暂时不需要JSX支持
- 选择
- 提示
Add Vue Router for Single Page Application development?
,是否添加Vue Router- 选择
Yes
,使用Vue Router作为路由工具
- 选择
- 提示
Add Pinia for state management?
,是否添加Pinia- 选择
Yes
,使用Pinia作为项目全局状态管理工具
- 选择
- 提示
Add Vitest for Unit Testing?
,是否添加Vitest- 选择
No
,暂不使用单元测试
- 选择
- 提示
Add an End-to-End Testing Solution?
,是否添加端到端测试方案- 选择
No
,暂不需要端到端的自动化测试
- 选择
- 提示
Add ESLint for code quality?
,是否添加ESLint- 选择
Yes
- 选择
- 提示
Add Prettier for code formatting?
,是否添加Prettier- 选择
Yes
,使用ESLint + Prettier作为代码质量检查工具
- 选择
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18> npm create vite@latest
Need to install the following packages:
create-vite@latest
Ok to proceed? (y) y
√ Project name: ... vite-project
√ Select a framework: » Vue
√ Select a variant: » Customize with create-vue ↗
Vue.js - The Progressive JavaScript Framework
√ Add TypeScript? ... No / Yes
√ Add JSX Support? ... No / Yes
√ Add Vue Router for Single Page Application development? ... No / Yes
√ Add Pinia for state management? ... No / Yes
√ Add Vitest for Unit Testing? ... No / Yes
√ Add an End-to-End Testing Solution? » No
√ Add ESLint for code quality? ... No / Yes
√ Add Prettier for code formatting? ... No / Yes等待项目构建,提示如下时说明构建完成
1
2
3
4
5
6
7
8Scaffolding project in E:\Other Project\vite\vite-project...
Done. Now run:
cd vite-project
npm install
npm run format
npm run dev项目结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18vite-project
|- node_modules
|- public
|- src
| |- assets
| |- components
| |- router
| |- stores
| |- views
| |- App.vue
| |- main.ts
|- .eslintrc.cjs
|- .prettierrc.json
|- index.html
|- package.json
|- tsconfig.json
|- vite.config.js
|- README.mdpackage.json:
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{
"name": "vite-project",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "run-p type-check build-only",
"preview": "vite preview",
"build-only": "vite build",
"type-check": "vue-tsc --noEmit",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
"format": "prettier --write src/"
},
"dependencies": {
"pinia": "^2.0.32",
"vue": "^3.2.47",
"vue-router": "^4.1.6"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.2.0",
"@types/node": "^18.14.2",
"@vitejs/plugin-vue": "^4.0.0",
"@vue/eslint-config-prettier": "^7.1.0",
"@vue/eslint-config-typescript": "^11.0.2",
"@vue/tsconfig": "^0.1.3",
"eslint": "^8.34.0",
"eslint-plugin-vue": "^9.9.0",
"npm-run-all": "^4.1.5",
"prettier": "^2.8.4",
"typescript": "~4.8.4",
"vite": "^4.1.4",
"vue-tsc": "^1.2.0"
}
}
二、使用Vue Cli构建项目
Vue Cli目前已不再更新,处于维护状态,可能会过时。
安装Vue Cli
- 打开
git bash
或cmd
或vscode
- 在命令行执行
npm install -g @vue/cli
- 打开
初始化项目
- 使用
git bash
或cmd
或vscode
打开一处文件夹 - 执行指令
vue create <项目名称>
- 接下来出现的选项,单选项可以通过方向键选择,或输入
Y
或N
进行是否选择,多选项通过空格选中,回车确认
- 接下来出现的选项,单选项可以通过方向键选择,或输入
- 提示
Please pick a preset:
,选择项目预设- 选择
Manually select feature
,手动选择所需功能
- 选择
- 提示
Check the features needed for your project:
,选择所需功能- 选中
Babel
、TypeScript
、Router
、Vuex
、Linter / Formatter
这几项 - Babel用于将ES6、ES7的语法转为ES5的语法
- 使用TypeScript作为项目的脚本语言
- 使用Router作为项目的路由工具
- 使用Vuex作为项目的全局状态管理工具
- 选中
Linter / Formatter
说明需要代码质量检查工具
- 选中
- 提示
Choose a version of Vue.js that you want to start the project with
,选择所用的Vue版本- 选择
3.x
,使用Vue3
- 选择
- 提示
Use class-style component syntax?
,是否使用类风格语法- 输入
N
,不使用
- 输入
- 提示
Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)?
,是否使用Babel自动为转换后的TypeScript代码注入polyfills- 输入
Y
,使用
- 输入
- 提示
Use history mode for router? (Requires proper server setup for index fallback in production)
,是否使用Router的历史模式- 输入
Y
,使用
- 输入
- 提示
Pick a linter / formatter config:
,选择代码检查工具- 选择
ESLint + Prettier
- 选择
- 提示
Pick additional lint features:
,选择何时进行代码检查- 选中
Lint on save
,在保存后检查
- 选中
- 提示
Where do you prefer placing config for Babel, ESLint, etc.?
,选择配置文件的存放位置- 选择
In dedicated config files
,为工具的配置分别生成独立文件,而不是都放在*package.json`中
- 选择
- 提示
Save this as a preset for future projects? (y/N)
,是否将本次的选项保存为预设- 输入
Y
或N
皆可,保存后可在之后新建项目时的第三步看到 Y
:提示Save preset as:
,为预设起名后回车
- 输入
- 等待项目构建
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15> vue create vue-project
Vue CLI v5.0.8
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, TS, Router, Vuex, Linter
? Choose a version of Vue.js that you want to start the project with 3.x
? Use class-style component syntax? No
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Pick a linter / formatter config: Prettier
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? Yes
? Save preset as: vue-ts- 使用
提示如下则构建成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24🎉 Preset vue-ts saved in C:\Users\zzz\.vuerc
Vue CLI v5.0.8
✨ Creating project in E:\Other Project\vue-project.
🗃 Initializing git repository...
⚙️ Installing CLI plugins. This might take a while...
added 885 packages in 2m
🚀 Invoking generators...
📦 Installing additional dependencies...
added 132 packages in 30s
⚓ Running completion hooks...
📄 Generating README.md...
🎉 Successfully created project vue-project.
👉 Get started with the following commands:
$ cd vue-project
$ npm run serve项目结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16vite-project
|- node_modules
|- public
|- src
| |- assets
| |- components
| |- router
| |- store
| |- views
| |- App.vue
| |- main.ts
|- .eslintrc.js
|- package.json
|- tsconfig.json
|- vue.config.js
|- README.mdpackage.json:
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{
"name": "vue-project",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.8.3",
"vue": "^3.2.13",
"vue-router": "^4.0.3",
"vuex": "^4.0.0"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.4.0",
"@typescript-eslint/parser": "^5.4.0",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-plugin-router": "~5.0.0",
"@vue/cli-plugin-typescript": "~5.0.0",
"@vue/cli-plugin-vuex": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"@vue/eslint-config-typescript": "^9.1.0",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.0.3",
"prettier": "^2.4.1",
"typescript": "~4.5.5"
}
}
组件安装与使用
往现有项目中添加组件的方式
- npm的
install
指令- 传统方式,安装组件包,手动写代码来引入所需内容
- Vue Cli的
vue add
指令- 将其他组件作为插件添加,可能会对现有代码进行变动,建议在commit后再添加
Vuex
老牌状态管理工具
npm方式
安装
- 执行
npm install vuex@next --save
安装Vuex
- 执行
引入
创建
src/store/
文件夹,在其中创建index.ts
文件,内容如下:1
2
3
4
5
6
7
8
9
10import { createStore } from "vuex";
export default createStore({
state: {},
getters: {},
mutations: {},
actions: {},
modules: {},
});在
src/main.ts
中使用store
:1
2
3
4
5import store from "@/store";
// ...
app.use(store);
版本:vuex@4.0.2
Vue Cli方式
- 执行
vue add vuex
,该指令会自动创建src/store/index.ts
,并在main.ts
中使用 - 版本:vuex@4.1.0
- 执行
使用范例
store/index.ts:
1
2
3
4
5
6
7
8
9
10
11
12import { createStore } from "vuex";
export default createStore({
state: {
counter: 0,
},
getters: {},
mutations: {},
actions: {},
modules: {},
});MyComponent.vue:
1
2
3
4
5
6
7
8
9
10<template>
<button @click="counter++">{{ counter }}</button>
</template>
<script setup lang="ts">
import { ref } from "vue";
import store from "@/store";
const counter = ref(store.state.counter);
</script>
Pinia
新的状态管理工具,API比Vuex更简单,提供了组合式API。
npm方式
安装
- 执行
npm install pinia
,安装Pinia
- 执行
引入
在
src/main.ts
中使用pinia
:1
2
3
4
5import { createPinia } from "pinia";
// ...
app.use(createPinia());
版本:pinia@2.0.32
vue-cli方式
- 执行
vue add vue-cli-plugin-pinia
,该指令会自动在main.ts
中使用Pinia,并在scr/store
或src/stores
下生成一个样例 - 版本:pinia@^2.0.28
- 执行
使用范例
store/counter.ts:
1
2
3
4
5
6
7
8
9
10
11
12
13import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})MyComponent.vue
:1
2
3
4
5
6
7
8
9<template>
<button @click="counter.count++">{{ counter.count }}</button>
</template>
<script setup lang="ts">
import { useCounterStore } from "@/store";
const counter = useCounterStore();
</script>
Vue Router
npm
方式:安装
- 执行
npm install vue-router@4
,安装Vue Router
- 执行
引入
创建
src/router
文件夹,在其中创建index.ts
文件,内容如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import('../views/AboutView.vue')
}
]
})
export default router将
routes
数组内容改为项目中的实际组件内容在
src/main.ts
中使用router
:1
2
3
4
5import router from "@/router";
// ...
app.use(router);
使用范例
router/index.ts:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
const routes: Array<RouteRecordRaw> = [
{
path: "/title",
name: "title",
component: () => import("../views/TitleView.vue"),
},
{
path: "/table",
name: "table",
component: () => import("../views/TableView.vue"),
},
];
const router = createRouter({
history: createWebHashHistory(process.env.BASE_URL),
routes,
});
export default router;App.vue:
1
2
3
4
5
6
7
8
9<template>
<router-view />
</template>
<script setup lang="ts">
import router from "@/router";
router.push("/title");
</script>TitleView.vue:
1
2
3
4
5
6
7<template>
<button @click="router.push('/table')">开始</button>
</template>
<script setup lang="ts">
import router from "@/router";
</script>TableView.vue:
1
2
3
4
5
6
7<template>
<button @click="router.back()">返回</button>
</template>
<script setup lang="ts">
import router from "@/router";
</script>
Vue3+组合式API+TypeScript
说到底,就是因为TypeScript、组合式API和setup语法糖写起来更舒服。
说明
- Vue3已不推荐使用class-style
- 通过
defineProps
这个全局方法来定义props
,需要默认值时则通过withDefaults
方法处理 - 所有顶层量都会默认可提供给模板使用
使用范例
MyComponent.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<template>
<div>{{ data }}</div>
<div>{{ computedData }}</div>
<button @click="func()">func button</button>
</template>
<script setup lang="ts">
import { computed, ref } from "vue";
/* props */
const props = defineProps<{
// ...
}>();
/* props with default */
export interface Props {
msg?: string
labels?: string[]
}
const props = withDefaults(defineProps<Props>(), {
msg: 'hello',
labels: () => ['one', 'two']
});
/* data */
const data = 1;
const msg = ref(props.msg);
/* computed */
const computedData = computed(() => data * 2);
/* methods */
function func(): void {
console.log("func");
}
</script>
问题与解决方案
cmd:无法加载文件 vue.ps1 因为在此系统上禁止运行脚本
问题:使用cmd执行vue指令时,可能会出现错误信息:cmd:无法加载文件 vue.ps1 因为在此系统上禁止运行脚本。
解决方案:以管理员身份运行cmd或者Windows PowerShell,执行set-ExecutionPolicy RemoteSigned
,选择A
。
项目打包后运行,页面空白
问题:通过npm run build
指令构建打包后本地打开index.html,页面全白无内容
使用
Vue Cli
的情况原因:默认资源路径错误与。
Vue Cli的默认资源路径为”/“,而非”./“。
解决方案:修改
vue.config.js
文件,添加publicPath
配置1
2
3
4
5
6const { defineConfig } = require("@vue/cli-service");
module.exports = defineConfig({
transpileDependencies: true,
publicPath: "./",
});使用
Vite
的情况原因:Vite打包后的项目不支持file引用协议,产生跨域错误,需要用服务器方式部署打开。
控制台:
1
Access to script at 'file:///xxx.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome, https, chrome-untrusted.
解决方案:不应使用这种方式来访问由Vite搭建的项目。
官方解释:故障排除 | Vite - 构建
希望可以直接通过打开index.html文件的方式来打开项目,实际上是希望可以有一个本地的图标入口来打开项目。这样的话可以考虑使用Electron进行包装,有待研究。
网络上有的方案是使用legacy插件并在项目build后做二次处理,这既不优雅也不合理。
路由404
问题:路由跳转后出现404错误
原因:路由模式错误。
Vue Router默认的历史记录模式为hash
的,但是对应的创建方法并不是与hash
对应的。
解决方案:修改routr/index.ts
文件,将router
的hostory
创建方法改为createWebHashHistory
1 | const router = createRouter({ |