Skip to content

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构建项目

Vite | 下一代的前端工具链

开发环境下的性能比Vue cli要快10~100倍。

  1. 初始化项目

    1. 使用_Git Bash_或_cmd_或_VSCode_打开一处文件夹
    2. 执行指令npm create vite@latest
      • 接下来出现的选项,单选项可以通过方向键选择,或输入YN进行是否选择,多选项通过空格选中,回车确认
    3. 若为初次使用,可能会提示Need to install the following packages: create-vite@latest Ok to proceed? (y),需要安装_create-vite_包
      • 输入y,确认安装
    4. 提示Project name:,输入项目名称
    5. 提示Select a framework:,选择一个前端框架
      • 选择Vue
    6. 提示Select a variant:,选择一种变体
      • 选择Customize with create-vue
        • 显示Vue.js - The Progressive JavaScript Framework标题,进入_Vue_的项目构建流程
    7. 提示Add TypeScript?,是否添加_TypeScript_
      • 选择Yes,使用_TypeScript_作为脚本语言
    8. 提示Add JSX Support?,是否添加JSX支持
      • 选择No,暂时不需要JSX支持
    9. 提示Add Vue Router for Single Page Application development?,是否添加_Vue Router_
      • 选择Yes,使用_Vue Router_作为路由工具
    10. 提示Add Pinia for state management?,是否添加_Pinia_
      • 选择Yes,使用_Pinia_作为项目全局状态管理工具
    11. 提示Add Vitest for Unit Testing?,是否添加_Vitest_
      • 选择No,暂不使用单元测试
    12. 提示Add an End-to-End Testing Solution?,是否添加端到端测试方案
      • 选择No,暂不需要端到端的自动化测试
    13. 提示Add ESLint for code quality?,是否添加_ESLint_
      • 选择Yes
    14. 提示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
  2. 等待项目构建,提示如下时说明构建完成

    Scaffolding project in E:\Other Project\vite\vite-project...
    
    Done. Now run:
    
    cd vite-project
    npm install
    npm run format
    npm run dev
  3. 项目结构

    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.md

    package.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目前已不再更新,处于维护状态,可能会过时。

  1. 安装_Vue Cli_

    1. 打开git bashcmdvscode
    2. 在命令行执行npm install -g @vue/cli
  2. 初始化项目

    1. 使用git bashcmdvscode打开一处文件夹
    2. 执行指令vue create <项目名称>
      • 接下来出现的选项,单选项可以通过方向键选择,或输入YN进行是否选择,多选项通过空格选中,回车确认
    3. 提示Please pick a preset:,选择项目预设
      • 选择Manually select feature,手动选择所需功能
    4. 提示Check the features needed for your project:,选择所需功能
      • 选中BabelTypeScriptRouterVuexLinter / Formatter这几项
      • _Babel_用于将ES6、ES7的语法转为ES5的语法
      • 使用_TypeScript_作为项目的脚本语言
      • 使用_Router_作为项目的路由工具
      • 使用_Vuex_作为项目的全局状态管理工具
      • 选中Linter / Formatter说明需要代码质量检查工具
    5. 提示Choose a version of Vue.js that you want to start the project with,选择所用的_Vue_版本
      • 选择3.x,使用_Vue3_
    6. 提示Use class-style component syntax?,是否使用类风格语法
      • 输入N,不使用
    7. 提示Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)?,是否使用_Babel_自动为转换后的TypeScript代码注入_polyfills_
      • 输入Y,使用
    8. 提示Use history mode for router? (Requires proper server setup for index fallback in production),是否使用_Router_的历史模式
      • 输入Y,使用
    9. 提示Pick a linter / formatter config:,选择代码检查工具
      • 选择ESLint + Prettier
    10. 提示Pick additional lint features:,选择何时进行代码检查
      • 选中Lint on save,在保存后检查
    11. 提示Where do you prefer placing config for Babel, ESLint, etc.?,选择配置文件的存放位置
      • 选择In dedicated config files,为工具的配置分别生成独立文件,而不是都放在*package.json`中
    12. 提示Save this as a preset for future projects? (y/N),是否将本次的选项保存为预设
      • 输入YN皆可,保存后可在之后新建项目时的第三步看到
      • Y:提示Save preset as:,为预设起名后回车
    13. 等待项目构建
    > 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
  3. 提示如下则构建成功

    🎉  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
  4. 项目结构

    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.md

    package.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"
      }
    }

组件安装与使用

往现有项目中添加组件的方式

  1. _npm_的install指令
    • 传统方式,安装组件包,手动写代码来引入所需内容
  2. _Vue Cli_的vue add指令
    • 将其他组件作为插件添加,可能会对现有代码进行变动,建议在commit后再添加

Vuex

Vuex

老牌状态管理工具

  1. _npm_方式

    1. 安装

      • 执行npm install vuex@next --save安装_Vuex_
    2. 引入

      1. 创建src/store/文件夹,在其中创建index.ts文件,内容如下:

        typescript
        import { createStore } from "vuex";
        
        export default createStore({
          state: {},
          getters: {},
          mutations: {},
          actions: {},
          modules: {},
        });
      2. src/main.ts中使用store

        typescript
        import store from "@/store";
        
        // ...
        
        app.use(store);
    3. 版本:vuex@4.0.2

  2. _Vue Cli_方式

    • 执行vue add vuex,该指令会自动创建src/store/index.ts,并在main.ts中使用
    • 版本:vuex@4.1.0
  3. 使用范例

    store/index.ts

    typescript
    import { 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

Pinia | 符合直觉的Vue.js 状态管理库

新的状态管理工具,API比Vuex更简单,提供了组合式API。

  1. _npm_方式

    1. 安装

      • 执行npm install pinia,安装_Pinia_
    2. 引入

      • src/main.ts中使用pinia

        typescript
        import { createPinia } from "pinia";
        
        // ...
        
        app.use(createPinia());
    3. 版本:pinia@2.0.32

  2. _vue-cli_方式

    • 执行vue add vue-cli-plugin-pinia,该指令会自动在main.ts中使用_Pinia_,并在scr/storesrc/stores下生成一个样例
    • 版本:pinia@^2.0.28
  3. 使用范例

    store/counter.ts

    typescript
    import { 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

Vue Router | Vue.js 的官方路由

  1. npm方式:

    1. 安装

      • 执行npm install vue-router@4,安装_Vue Router_
    2. 引入

      1. 创建src/router文件夹,在其中创建index.ts文件,内容如下:

        typescript
        import { 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
      2. routes数组内容改为项目中的实际组件内容

      3. src/main.ts中使用router

        typescript
        import router from "@/router";
        
        // ...
        
        app.use(router);
    3. 版本:vue-router@4.1.6

  2. 使用范例

    router/index.ts

    typescript
    import { 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

<script setup>

组合式 API 常见问答

说到底,就是因为TypeScript、组合式API和setup语法糖写起来更舒服。

  1. 说明

    1. Vue3_已不推荐使用_class-style
    2. 通过defineProps这个全局方法来定义props,需要默认值时则通过withDefaults方法处理
    3. 所有顶层量都会默认可提供给模板使用
  2. 使用范例

    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_,页面全白无内容

  1. 使用Vue Cli的情况

    原因:默认资源路径错误与。

    _Vue Cli_的默认资源路径为”/“,而非”./“。

    解决方案:修改vue.config.js文件,添加publicPath配置

    javascript
    const { defineConfig } = require("@vue/cli-service");
       module.exports = defineConfig({
       transpileDependencies: true,
       publicPath: "./",
    });
  2. 使用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文件,将routerhostory创建方法改为createWebHashHistory

typescript
const router = createRouter({
   history: createWebHashHistory(process.env.BASE_URL),
   routes,
});