信息发布→ 登录 注册 退出

Vue3+TS+Vite+NaiveUI搭建一个项目骨架实现

发布时间:2026-01-11

点击量:
目录
  • 写在前面
  • 创建Vue3项目
  • 开发规范
  • Vite配置
    • 别名配置
    • 环境变量
      • .env文件
      • 定义环境变量
      • 在vite.config.ts中获取环境变量
    • 自动导入
    • NaiveUI的安装
      • 写在最后

        写在前面

        现在已经有很多项目团队使用Vue3+TS进行开发,同时也就意味着Vue3的生态越来越完善,如果还是停留在Vue2的阶段已经out了,这篇文章将会使用Vue3+TS+NaivaUI搭建一个简单的项目骨架。

        创建Vue3项目

        首先我们通过Vite来创建一个Vue3+TS的一个项目,打开终端,找到我们项目应该存放的目录,出书如下命令:

        npm create vite@latest

        如果你是第一次使用Vite,需要先输入y,然后回依次出现:

        • 项目名称(想叫什么叫什么)

        • 框架(这里选择的是Vue)

        • Variant(这里选择的是Vue3+TS)

        键入回车后等待一会项目就创建好了,然后进入项目安装依赖就好。

        开发规范

        这里对开发规范的配置仅配置ESLint,其他的StyleLint、git提交验证这里不进行介绍;这里还会安装Prettier,用于代码格式化。

        首先安装依赖:

        npm i -D eslint eslint-plugin-vue eslint-define-config # eslink
        npm i -D prettier eslint-plugin-prettier @vue/eslint-config-prettier # prettire
        npm i -D @vue/eslint-config-typescript @typescript-eslint/eslint-plugin @typescript-eslint/parser # 对ts的支持
        

        然后我们依次编写一下对应的配置文件:

        ESLint风格检查配置文件:.eslintrc.js

        const { defineConfig } = require('eslint-define-config')
        
        module.exports = defineConfig({
          root: true,
          /* 指定如何解析语法。*/
          parser: 'vue-eslint-parser',
          /* 优先级低于parse的语法解析配置 */
          parserOptions: {
            parser: '@typescript-eslint/parser',
            //模块化方案
            sourceType: 'module',
          },
          env: {
            browser: true,
            es2025: true,
            node: true,
            // 解决 defineProps and defineEmits generate no-undef warnings
            'vue/setup-compiler-macros': true,
          },
          // https://eslint.bootcss.com/docs/user-guide/configuring#specifying-globals
          globals: {},
          extends: [
            'plugin:vue/vue3-recommended',
            'eslint:recommended',
            'plugin:@typescript-eslint/recommended', // typescript-eslint推荐规则,
            'prettier',
            'plugin:prettier/recommended',
          ],
          // https://cn.eslint.org/docs/rules/
          rules: {
            // 禁止使用 var
            'no-var': 'error',
            semi: 'off',
            // 优先使用 interface 而不是 type
            '@typescript-eslint/consistent-type-definitions': ['error', 'interface'],
            '@typescript-eslint/no-explicit-any': 'off', // 可以使用 any 类型
            '@typescript-eslint/explicit-module-boundary-types': 'off',
            // 解决使用 require() Require statement not part of import statement. 的问题
            '@typescript-eslint/no-var-requires': 0,
            // https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/ban-types.md
            '@typescript-eslint/ban-types': [
              'error',
              {
                types: {
                  // add a custom message to help explain why not to use it
                  Foo: "Don't use Foo because it is unsafe",
        
                  // add a custom message, AND tell the plugin how to fix it
                  String: {
                    message: 'Use string instead',
                    fixWith: 'string',
                  },
        
                  '{}': {
                    message: 'Use object instead',
                    fixWith: 'object',
                  },
                },
              },
            ],
            // 禁止出现未使用的变量
            '@typescript-eslint/no-unused-vars': [
              'error',
              { vars: 'all', args: 'after-used', ignoreRestSiblings: false },
            ],
            'prettier/prettier': [
              'error',
              { singleQuote: true, parser: 'flow', semi: false },
            ],
            'vue/html-indent': 'off',
            // 关闭此规则 使用 prettier 的格式化规则,
            'vue/max-attributes-per-line': ['off'],
            // 优先使用驼峰,element 组件除外
            'vue/component-name-in-template-casing': [
              'error',
              'PascalCase',
              {
                ignores: ['/^el-/', '/^router-/'],
                registeredComponentsOnly: false,
              },
            ],
            // 强制使用驼峰
            camelcase: ['error', { properties: 'always' }],
            // 优先使用 const
            'prefer-const': [
              'error',
              {
                destructuring: 'any',
                ignoreReadBeforeAssign: false,
              },
            ],
          },
        })
        
        

        Prettier的代码格式化配置文件:prettierrc.js

        module.exports = {
          // 结尾分号
          semi: false,
          // 单引号
          singleQuote: true,
          // 一行80字符
          printWidth: 80,
          // 尾逗号
          trailingComma: 'all',
          // 箭头函数的括号
          arrowParens: 'avoid',
          // 换行符
          endOfLine: 'lf',
        }

        配置ESLint的代码检测忽略的文件的配置文件:.eslintignore

        /node_modules/
        /public/
        .vscode
        .idea

        Vite配置

        别名配置

        配置别名可以帮助我们快速的找到我们想要的组件、图片等内容,不用使用../../../的方式,首先配置vite.config.ts,通过resolve.alias的方式配置,示例代码如下:

        import { defineConfig } from 'vite'
        import type { ConfigEnv } from 'vite'
        import vue from '@vitejs/plugin-vue'
        import { resolve } from 'path'
        
        // https://vitejs.dev/config/
        export default defineConfig(({ mode }: ConfigEnv) => {
          return {
            resolve: {
              alias: {
                '/@': resolve(__dirname, 'src'),
              },
              extensions: ['.js', '.json', '.ts', '.vue'], // 使用路径别名时想要省略的后缀名,可以自己 增减
            },
        
            /* more config */
            plugins: [vue()],
          }
        })

        这里配置一个/@的别名,它指向src目录,然后配置tsconfig.json,允许别名在使用,代码如下:

        "compilerOptions": {
          // 用于设置解析非相对模块名称的基本目录,相对模块不会受到baseUrl的影响
          "baseUrl": ".",
          "paths": {
            // 用于设置模块名到基于baseUrl的路径映射
            "/@/*": [ "src/*" ],
          }
        },
        

        环境变量

        .env文件

        在Vite中通过.env开头的文件去读取配置,来作为环境变量,Vite默认允许我们使用以下文件:

        .env                # 所有情况下都会加载
        .env.local          # 所有情况下都会加载,但会被 git 忽略
        .env.[mode]         # 只在指定模式下加载
        .env.[mode].local   # 只在指定模式下加载,但会被 git 忽略
        

        这些文件是有优先级的,他们的优先级是.env<.env.local<.env.[mode]<.env.[mode].local;Vite中还预设了一些环境变量,这些的优先级是最高的,不会被覆盖,分别如下:

        • MODE: {string}:应用运行的模式(开发环境下为development,生成环境为production)。

        • BASE_URL: {string}:部署应用时的基本 URL。他由base 配置项决定。

        • PROD: {boolean}:当前是否是生产环境。

        • DEV: {boolean}:当前是否是开发环境 (永远与 PROD相反)。

        这些环境变量Vite允许我们通过import.meto.env方式获取。

        定义环境变量

        如果我么你想要自定义环境变量,就必须以VITE_开头,如果修改则需要通过envPrefix配置项,该配置项允许我们传入一个非空的字符串作为变量的前置。

        .env

        VITE_APP_API_BASE_URL=http://127.0.0.1:8080/
        

        定义完成之后我们就可以在项目中通过import.meta.env.VITE_APP_API_BASE_URL的方式获取。

        如果想要获得TypeScript的类型提示,需要在创建一个src/type/env.d.ts(把原src目录下的env.d.ts删除),示例代码如下:

        /// <reference types="vite/client" />
        
        interface ImportMetaEnv {
          readonly VITE_APP_API_BASE_URL: string
          // 定义更多环境变量
        }
        
        interface ImportMeta {
          readonly env: ImportMetaEnv
        }
        
        declare module '*.vue' {
          import type { DefineComponent } from 'vue'
          // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
          const component: DefineComponent<{}, {}, any>
          export default component
        }

        在使用时就会获得智能提示。

        在vite.config.ts中获取环境变量

        如果我们想要在vite.config.ts中获取环境变量,需要使用Vite提供的loadEnv()方法,该方法的定义如下:

        function loadEnv(
          mode: string, 
          envDir: string, 
          prefixes?: string | string[]
        ): Record<string, string>
        

        上面的三个参数的解释如下:

        • mode:模式;

        • envDir:环境变量配置文件所在目录;

        • prefixes:【可选】接受的环境变量前缀,默认为VITE_

        了解了使用的API,在vite.config.ts中获取环境变量示例代码如下:

        import { defineConfig, loadEnv } from 'vite'
        import vue from '@vitejs/plugin-vue'
        import AutoImport from 'unplugin-auto-import/vite'
        import Components from 'unplugin-vue-components/vite'
        import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
        import type { ConfigEnv } from 'vite'
        
        // https://vitejs.dev/config/
        export default defineConfig(({ mode }: ConfigEnv) => {
          const env = loadEnv(mode, process.cwd())
          return {
            /* more config */
            server: {
              proxy: {
                '/api': {
                  target: env.VITE_APP_API_BASE_URL,
                  changeOrigin: true,
                  rewrite: path => path.replace(/^\/api/, ''),
                },
              },
            },
          }
        })
        
        

        自动导入

        在使用setup语法糖进行开发的过程中,一些常用的API比如watchref等,需要每次都进行导入,而且组件如果是按需导入的话也需要进行导入,我们可以通过Vite的插件来帮助我们实现自动导入:

        • unplugin-vue-components:组件按需导入;

        • unplugin-auto-importvue, vue-router, vue-i18n, @vueuse/head, @vueuse/core等自动导入;

        安装命令如下:

        npm i -D unplugin-vue-components unplugin-auto-import
        

        然后在vite.config.ts中导入并配置:

        import { defineConfig, loadEnv } from 'vite'
        import type { ConfigEnv } from 'vite'
        import vue from '@vitejs/plugin-vue'
        import { resolve } from 'path'
        import AutoImport from 'unplugin-auto-import/vite'
        import Components from 'unplugin-vue-components/vite'
        
        // https://vitejs.dev/config/
        export default defineConfig(({ mode }: ConfigEnv) => {
          const env = loadEnv(mode, process.cwd())
          return {
            resolve: {
              alias: {
                '/@': resolve(__dirname, 'src'),
              },
              extensions: ['.js', '.json', '.ts', '.vue'], // 使用路径别名时想要省略的后缀名,可以自己 增减
            },
        
            /* more config */
            plugins: [
              vue(),
              AutoImport({
                resolvers: [],
                // 自定引入 Vue VueRouter API,如果还需要其他的可以自行引入
                imports: ['vue', 'vue-router'],
                // 调整自动引入的文件位置
                dts: 'src/type/auto-import.d.ts',
                // 解决自动引入eslint报错问题 需要在eslintrc的extend选项中引入
                eslintrc: {
                  enabled: true,
                  // 配置文件的位置
                  filepath: './.eslintrc-auto-import.json',
                  globalsPropValue: true,
                },
              }),
              Components({
                resolvers: [
                  // 需要自动导入的组件
                ],
                dts: 'src/type/components.d.ts',
              }),
            ],
          }
        })
        
        

        现在我们可以在项目中直接使用Vue和VueRouter的所有API。

        但是现在还有一个问题就是ESLint对自动引入的API报错,解决办法如下:

        // 在.eslintrc.js中的extends配置项加入'./.eslintrc-auto-import.json',
        extends: [
          'plugin:vue/vue3-recommended',
          'eslint:recommended',
          'plugin:@typescript-eslint/recommended', // typescript-eslint推荐规则,
          'prettier',
          'plugin:prettier/recommended',
          './.eslintrc-auto-import.json',
        ],

        NaiveUI的安装

        Q:众多UI组件库这里为什么选择NaiveUI?

        A1:NaiveUI的官方文档对于其他UI组件库来说生动有趣;

        A2:尤大推荐过;

        A3:组件数量庞大;

        安装依赖命令如下:

        npm i -D naive-ui @vicons/ionicons5 # @vicons/ionicons5是icon的库
        

        配置NaiveUI自动导入功能,打开vite.config.ts,从unplugin-vue-components/resolvers中引入NaiveUiResolver,并添加的在plugin中,示例代码如下:

        Components({
          resolvers: [
            // 需要自动导入的组件
            NaiveUiResolver()
          ],
          dts: 'src/type/components.d.ts',
        }),
        

        现在就已经把 NaiveUI安装并引入了,其实很简单。

        现在我们来使用一下这个UI组件库,这里就直接在App.vue中编写了,示例代码如下:

        <script setup lang="ts">
        import { zhCN, zhTW, dateZhCN, dateZhTW, darkTheme, lightTheme } from 'naive-ui'
        import { Sunny, Moon } from '@vicons/ionicons5'
        type LocaleType = 'zhCN' | 'zhTW'
        const locale = ref<LocaleType>('zhCN')
        const isDark = ref(false)
        const langOpt = [
          { label: '简体中文', key: 'zhCN' },
          { label: '繁体中文', key: 'zhTW' },
        ]
        const langList = {
          zhCN: { locale: zhCN, label: '简体中文', dataLocale: dateZhCN },
          zhTW: { locale: zhTW, label: '繁体中文', dataLocale: dateZhTW },
        }
        const handleSelect = (e: LocaleType) => {
          locale.value = e
        }
        </script>
        <template>
          <NConfigProvider
            :locale="langList[locale].locale"
            :date-locale="langList[locale].dataLocale"
            :theme="isDark === true ? darkTheme : lightTheme"
          >
            <NGlobalStyle />
            <!-- vue-router占位 -->
            <router-view/>
          </NConfigProvider>
        </template>
        <style></style>
        
        

        在里面展示了一部分组件,运行效果如下:

        写在最后

        这篇文章到这里就结束了,其实还有好多东西没有安装和配置,比如VueRouter、Pinia,还可以安装TailWindCSS,这些依赖的安装方式比较简单,官网都有比较完整的安装方式,这里就不啰嗦了。

        在线客服
        服务热线

        服务热线

        4008888355

        微信咨询
        二维码
        返回顶部
        ×二维码

        截屏,微信识别二维码

        打开微信

        微信号已复制,请打开微信添加咨询详情!