Vue3项目快速搭建

593 阅读6分钟

Vue3项目快速搭建

  • 技术栈:Vue3PiniaVueRouterViteElementPlusTypeScriptEcharts
  • 包管理器:pnpm

一、项目初始化

1. 创建项目

  • 安装create-vue

    pnpm create vue@latest
    

    这一指令将会安装并执行 create-vue,它是 Vue 官方的项目脚手架工具。你将会看到一些诸如 TypeScript 和测试支持之类的可选功能提示。

    image.png

2. 项目代码规范搭建

规范团队开发,让团队开发风格保持一致。

以下很多插件都是创建项目时已勾选,会帮我们进行一些默认的配置,注意检查就好。

创建 Vue 项目时勾选 ESLintPrettier,几乎给你配置好了格式化。

1. 集成 editorconfig 配置

EditorConfig 有助于为不同 IDE 编辑器上处理同⼀项⽬的多个开发⼈员维护⼀致的编码⻛格。

  • 在项目根目录 / 下新建 .editorconfig 文件:

    # http://editorconfig.org
    
    root = true
    
    [*] # 表示所有⽂件适⽤
    charset = utf-8 # 设置⽂件字符集为 utf-8
    indent_style = space # 缩进⻛格(tab | space)
    indent_size = 2 # 缩进⼤⼩
    end_of_line = lf # 控制换⾏类型(lf | cr | crlf)
    trim_trailing_whitespace = true # 去除⾏尾的任意空⽩字符
    insert_final_newline = true # 始终在⽂件末尾插⼊⼀个新⾏
    
    [*.md] # 表示仅 md ⽂件适⽤以下规则
    max_line_length = off
    trim_trailing_whitespace = false
    
  • VSCode需要安装⼀个插件:EditorConfig for VS Code

    image.png

2. 使⽤ prettier ⼯具

Prettier 是⼀款强⼤的代码格式化⼯具,⽀持 JavaScriptTypeScriptCSSSCSSLessJSXAngularVueGraphQLJSONMarkdown 等语⾔,基本上前端能⽤到的⽂件格式它都可以搞定,是当下最流⾏的代码格式化⼯具。

  • 安装prettier

    pnpm install prettier -D
    
  • 配置.prettierrc⽂件:

    {
     "useTabs": false,
     "tabWidth": 2,
     "printWidth": 80,
     "singleQuote": true,
     "trailingComma": "none",
     "semi": false
    }
    
    • useTabs:使⽤tab缩进还是空格缩进,选择 false
    • tabWidthtab是空格的情况下,是⼏个空格,选择2个;
    • printWidth:当⾏字符的⻓度,推荐80,也有⼈喜欢100或者120;
    • singleQuote:使⽤单引号还是双引号,选择true,使⽤单引号;
    • trailingComma:在多⾏输⼊的尾逗号是否添加,设置为 none ,⽐如对象类型的最后⼀个属性后⾯是否加⼀个,;
    • semi:语句末尾是否要加分号,默认值true,选择false表示不加;
  • 创建.prettierignore忽略⽂件

    /dist/*
    .local
    .output.js
    /node_modules/**
    
    **/*.svg
    **/*.sh
    /public/*
    
  • VSCode需要安装prettier的插件

    image.png

  • VSCod中的配置

    1. settings =>format on save => 勾选上
    2. settings => editor default format => 选择 prettier
    3. package.json 中配置⼀个 scripts
      "prettier": "prettier --write ."
      
  • 测试 prettier 是否⽣效

    1. 测试⼀:在代码中保存代码;
    2. 测试⼆:配置⼀次性修改的命令;
3. 使⽤ESLint检测
  1. 在前⾯创建项⽬的时候,我们就选择了 ESLint,所以 Vue 会默认帮助我们配置需要的 ESLint 环境。

  2. VSCode需要安装 ESLint 插件:

    image.png

  3. 解决 eslintprettier 冲突的问题:

    • 安装插件:vue 在创建项⽬时,如果选择 prettier,那么这两个插件会⾃动安装)

      pnpm install eslint-plugin-prettier eslint-config-prettier -D
      
    • 添加 prettier 插件:

      extends: [
         "plugin:vue/vue3-essential",
         "eslint:recommended",
         "@vue/typescript/recommended",
         "@vue/prettier",
         "@vue/prettier/@typescript-eslint",
         'plugin:prettier/recommended'
       ],
      
  4. VSCodeeslint 的配置

     "eslint.lintTask.enable": true,
     "eslint.alwaysShowStatus": true,
     "eslint.validate": [
       "javascript",
       "javascriptreact",
       "typescript",
       "typescriptreact"
    ],
     "editor.codeActionsOnSave": {
       "source.fixAll.eslint": true
     },
    

3. 项目开发

1. CSS 样式重置
  • 使用 normalize.css

    normalize.css是一个很小的CSS文件,它默认的HTML元素样式上提供了跨浏览器的高度一致性,相比传统的CSS resetnormalize.css 是一种现代的、为HTML5准备的优质替代方案

    • 下载 normalize.css

      pnpm install normalize.css
      
    • main.ts中引入

      import 'normalize.css'
      
  • 创建 reset.lesscommon.less

    reset.less用于自定义重置网站的CSS样式,common.less用于网站的公用样式。

    • 安装 lessless-loader

      pnpm install less less-loader
      
    • vite.config.ts 中配置

      export default defineConfig({
        plugins: [
          vue(),
        ],
        
        //配置css变量
        css: {
          preprocessorOptions: {
            less: {
              javascriptEnabled: true,
            },
          },
        },
      })
      
    • 分别创建 reset.lesscommon.less,并通过 index.less 统一导出

      @import './reset.less';
      @import './common.less';
      
    • mian.ts中引入index.less

      import '@/assets/css/index.less'
      
2. Vue-Router 配置
  • src下新建文件夹:routerviews

  • 安装vue-router

    pnpm install vue-router
    
  • 创建index.ts进行路由配置

    import { createRouter, createWebHashHistory } from 'vue-router'
    
    const router = createRouter({
      history: createWebHashHistory(),
      routes: [
        {
          path: '/',
          redirect: '/login',
        },
        {
          path: '/login',
          component: () => import('@/views/login/login.vue'),
        },
        {
          path: '/main',
          component: () => import('@/views/main/main.vue'),
        },
        {
          path: '/:pathMatch(.*)',
          component: () => import('@/views/not-found/404.vue'),
        },
      ],
    })
    
    export default router
    

可能会出现两个小问题,虽然都不影响程序正常运行,但看着不舒服。

  • views 中的页面开头会报红线
  • index.ts 文件中 import("url") 报红线

eslint.config.ts 中 添加规则配置

import pluginVue from 'eslint-plugin-vue'
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'

export default defineConfigWithVueTs(
  pluginVue.configs['flat/essential'],
  vueTsConfigs.recommended,
  skipFormatting,
  // 添加规则配置
  {
    rules: {
      // 强制 Vue 组件名使用多词形式
      'vue/multi-word-component-names': 'off',
      // 关闭any类型的警告。
      '@typescript-eslint/no-explicit-any': ['off'],
    },
  },
)
3. pinia 配置
  • 安装 Pinia

    pnpm install pinia
    
  • 引入 Pinia

    创建 store 文件夹与 index.ts 文件

    • 创建 pinia 应用入口 index.ts

      import { createPinia } from 'pinia'
      import type { App } from 'vue'
      
      const pinia = createPinia()
      
      function registerStore(app: App<Element>) {
        app.use(pinia)
      }
      
      export default registerStore
      
    • main.ts 中注册 pinia

      import { createApp } from 'vue'
      import App from './App.vue'
      import store from './store/index'
      
      const app = createApp(App)
      app.use(store)
      
      app.mount('#app')
      
  • 定义Store

    • store 文件夹下新建 login 文件夹,新建 login.ts 文件去定义 Store

      import { defineStore } from 'pinia'
      
      const useLoginStore = defineStore('login', {
        state: () => ({
          num: 0,
        }),
        actions: () => ({}),
      })
      
      export default useLoginStore
      
  • 使用 Store

    • store 是一个用 reactive 包裹的对象,就像 setup 中的 props 一样,我们不能对其进行解构。这样拿到的数据不是响应式的。为了从 Store 中提取属性同时保持其响应式,您需要使用 storeToRefs()

    • 它将为任何响应式属性创建 refs。 当您仅使用 store 中的状态但不调用任何操作时,这很有用:

      <script setup lang="ts">
      import useLoginStore from '@/store/login/login'
      const loginStore = useLoginStore()
      
      </script>
      
      <template>
        <div class="main">
            {{ loginStore.num }}
        </div>
      </template>
      
4. axios 网络请求封装
  • 安装axios

    npm install axios
    
  • 导入封装好的service文件夹

区分 developmentproduction 环境

Vite的环境变量:

  • Vite 在一个特殊的import.meta.env对象上暴露环境变量。

    这里有一些在所有情况下都可以使用的内建变量:

    • import.meta.env.MODE: {string} 应用运行的模式。

    • import.meta.env.PROD: {boolean} 应用是否运行在生产环境。

    • import.meta.env.DEV: {boolean} 应用是否运行在开发环境 (永远与 import.meta.env.PROD相反)。

    • import.meta.env.SSR: {boolean} 应用是否运行在 server 上。

  • Vite 使用 dotenv 从你的 环境目录 中的下列文件加载额外的环境变量:

  • 只有以 VITE_ 为前缀的变量才会暴露给经过 vite 处理的代码。

5. Element-Plus集成
  • 安装element-plus

    pnpm install element-plus
    
  • 按需引入

    • 首先需要安装 unplugin-vue-componentsunplugin-auto-import 两款插件

      pnpm install -D unplugin-vue-components unplugin-auto-import
      
    • 然后把下列代码插入到你的 ViteWebpack 的配置文件中

      • Vite
      import { defineConfig } from 'vite'
      import AutoImport from 'unplugin-auto-import/vite'
      import Components from 'unplugin-vue-components/vite'
      import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
      
      export default defineConfig({
        // ...
        plugins: [
          // ...
          AutoImport({
            resolvers: [ElementPlusResolver()],
          }),
          Components({
            resolvers: [ElementPlusResolver()],
          }),
        ],
      })
      
      • Webpack
      const AutoImport = require('unplugin-auto-import/webpack')
      const Components = require('unplugin-vue-components/webpack')
      const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
      
      module.exports = {
        // ...
        plugins: [
          AutoImport({
            resolvers: [ElementPlusResolver()],
          }),
          Components({
            resolvers: [ElementPlusResolver()],
          }),
        ],
      }
      

二、权限管理

1. 记住密码功能实现

  • 通过监听isKeep值的变化去判断是否应该使用本地持久化存储记录密码。

    // 定义记住密码boolean值
    const isKeep = ref<boolean>(localCache.getCache('rem_pwd'))
    // 监听记住密码值的变化
    watch(isKeep, (newValue) => {
      // 持久化存储到 localCache
      localCache.setCache('rem_pwd', newValue)
    })
    
    // 用户登录
    function loginAction(isKeep: boolean) {
      // 是否通过了验证
      formRef.value?.validate((isValid) => {
        if (isValid) {
          // 根据isKeep值判断是否记住密码
          if (isKeep) {
            localCache.setCache('name', name)
            localCache.setCache('password', password)
          } else {
            localCache.deleteCache('name')
            localCache.deleteCache('password')
          }
        } else {
          ElMessage.warning({ message: '账号或者密码输入的规则错误~' })
        }
      })
    }
    

2. 用户登录