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_作为代码质量检查工具
- 选择
> 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等待项目构建,提示如下时说明构建完成
Scaffolding project in E:\Other Project\vite\vite-project... Done. Now run: cd vite-project npm install npm run format npm run dev项目结构
vite-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:
json{ "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:,为预设起名后回车
- 输入
- 等待项目构建
> 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- 使用
提示如下则构建成功
🎉 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项目结构
vite-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:
json{ "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文件,内容如下:typescriptimport { createStore } from "vuex"; export default createStore({ state: {}, getters: {}, mutations: {}, actions: {}, modules: {}, });在
src/main.ts中使用store:typescriptimport 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:
typescriptimport { createStore } from "vuex"; export default createStore({ state: { counter: 0, }, getters: {}, mutations: {}, actions: {}, modules: {}, });MyComponent.vue:
<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:typescriptimport { 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:
typescriptimport { 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:<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文件,内容如下:typescriptimport { 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:typescriptimport router from "@/router"; // ... app.use(router);
使用范例
router/index.ts:
typescriptimport { 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:
<template> <router-view /> </template> <script setup lang="ts"> import router from "@/router"; router.push("/title"); </script>TitleView.vue:
<template> <button @click="router.push('/table')">开始</button> </template> <script setup lang="ts"> import router from "@/router"; </script>TableView.vue:
<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:
<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配置javascriptconst { defineConfig } = require("@vue/cli-service"); module.exports = defineConfig({ transpileDependencies: true, publicPath: "./", });使用
Vite的情况原因:_Vite_打包后的项目不支持file引用协议,产生跨域错误,需要用服务器方式部署打开。
控制台:
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
const router = createRouter({
history: createWebHashHistory(process.env.BASE_URL),
routes,
});