vue3+ts+pinia脚手架搭建

180 阅读6分钟

1、创建项目

进入cmd 或 iterm 选择创建项目的路径后, 运行 yarn create vite 然后根据提示输入项目名称、依次选择vue、TypeScript。cd进入项目输入yarn安装依赖

Project name(项目名称): … marriage-b-h5
Select a framework(选择框架): › Vue
Select a variant(选择变体): › TypeScript

2、代码规范

2-1、配置EsLint

//安装EsLint
yarn add -D eslint

//初始化配置EsLint
npx eslint --init

How would you like to use ESLint? 选 To check syntax and find problems What type of modules does your project use? 选 JavaScript modules (import/export) Which framework does your project use?选 Vue.js
Does your project use TypeScript?选 Yes
Where does your code run?选 Browser What format do you want your config file to be in?选 JavaScript
Would you like to install them now? 选 Yes
Which package manager do you want to use?选 yarn

WeChat5e45ff41e13e60807a61eeafa7c8d292.jpg 按需选择完后Eslint会帮我们创建.eslintrc.cjs

在 package.json 的 script 中添加命令

"scripts": { "lint": "eslint --ext .ts,.vue,.js, --fix --quiet ./" },

在App.vue中添加一个未使用的变量a

WeChatb69b245ab40eacf9b749859b75c7c5c0.jpg 运行yarn lint ,如果报错,说明Eslint配置生效

WeChate668535d69e10374db3e8200483f73c5.jpg

2-2、配置Prettier

一般 ESLint 用于检测代码风格代码规范,Prettier 用于对代码进行格式化。

yarn add prettier -D

然后在根目录创建 .prettierrc.cjs 配置文件,复制下面代码到文件中

module.exports = {
    tabWidth: 4,
    jsxSingleQuote: true,
    jsxBracketSameLine: true,
    printWidth: 80,
    singleQuote: true,
    semi: false,
    overrides: [
        {
            files: '*.json',
            options: {
                printWidth: 200,
            },
        },
    ],
    arrowParens: 'always',
    endOfLine: 'auto',
}

在 package.json 的 script 中添加命令

"prettier":"prettier --write ./src/App.vue"

运行yarn prettier后,代码已经格式化,说明prettier配置有效

2-3、EsLint+Prettier

在eslint校验中加入Prettier格式化

yarn add eslint-config-prettier eslint-plugin-prettier -D

更改 Eslint 的配置文件 .eslintrc.cjs, 在里面加入 Prettier 相关配置

module.exports = {
    root: true,
    env: {
        browser: true,
        node: true,
        es6: true,
    },
    parser: 'vue-eslint-parser',
    parserOptions: {
        parser: '@typescript-eslint/parser',
        ecmaVersion: 2020,
        sourceType: 'module',
        jsxPragma: 'React',
        ecmaFeatures: {
            jsx: true,
        },
    },
    extends: [
        'plugin:vue/vue3-recommended',
        'plugin:@typescript-eslint/recommended',
        'prettier',
        'plugin:prettier/recommended',
    ],
    rules: {
        'vue/script-setup-uses-vars': 'error',
        '@typescript-eslint/ban-ts-ignore': 'off',
        '@typescript-eslint/explicit-function-return-type': 'off',
        '@typescript-eslint/no-explicit-any': 'off',
        '@typescript-eslint/no-var-requires': 'off',
        '@typescript-eslint/no-empty-function': 'off',
        'vue/custom-event-name-casing': 'off',
        'no-use-before-define': 'off',
        '@typescript-eslint/no-use-before-define': 'off',
        '@typescript-eslint/ban-ts-comment': 'off',
        '@typescript-eslint/ban-types': 'off',
        '@typescript-eslint/no-non-null-assertion': 'off',
        '@typescript-eslint/explicit-module-boundary-types': 'off',
        '@typescript-eslint/no-unused-vars': [
            'error',
            {
                argsIgnorePattern: '^_',
                varsIgnorePattern: '^_',
            },
        ],
        'no-unused-vars': [
            'error',
            {
                argsIgnorePattern: '^_',
                varsIgnorePattern: '^_',
            },
        ],
        'space-before-function-paren': 'off',
        'vue/one-component-per-file': 'off',
        'vue/html-closing-bracket-newline': 'off',
        'vue/multiline-html-element-content-newline': 'off',
        'vue/singleline-html-element-content-newline': 'off',
        'vue/attribute-hyphenation': 'off',
        'vue/require-default-prop': 'off',
        'vue/require-explicit-emits': 'off',
        'vue/no-dupe-keys': 'off',
        'vue/html-self-closing': [
            'error',
            {
                html: {
                    void: 'always',
                    normal: 'never',
                    component: 'always',
                },
                svg: 'always',
                math: 'always',
            },
        ],
        // 'vue/multi-word-component-names': [
        //     'error',
        //     {
        //         ignores: [],
        //     },
        // ],
        'vue/multi-word-component-names': 'off',
        // 组件名大小写
        'vue/component-name-in-template-casing': [
            'error',
            'kebab-case',
            {
                registeredComponentsOnly: false,
                ignores: [],
            },
        ],
        // 给v-for设置键值,与key结合使用
        'vue/require-v-for-key': 'error',
        // 元素/组件特性的顺序v-for、v-if、v-else-if、v-else、v-show、id、ref、key...
        'vue/attributes-order': [
            'error',
            {
                order: [
                    'DEFINITION',
                    'LIST_RENDERING',
                    'CONDITIONALS',
                    'RENDER_MODIFIERS',
                    'GLOBAL',
                    ['UNIQUE', 'SLOT'],
                    'TWO_WAY_BINDING',
                    'OTHER_DIRECTIVES',
                    'OTHER_ATTR',
                    'EVENTS',
                    'CONTENT',
                ],
                alphabetical: false,
            },
        ],
        // 多个特性的元素应该分多行撰写,每个特性一行
        'vue/max-attributes-per-line': 'off',
        // 'vue/max-attributes-per-line': [
        //     'error',
        //     {
        //         singleline: 1,
        //         multiline: {
        //             max: 1,
        //             allowFirstLine: false,
        //         },
        //     },
        // ],
    },
}

3、安装pinia

yarn add pinia

//数据持久化
yarn add pinia-plugin-persist
yarn add pinia-plugin-persistedstate

3-1、创建pinia实例

新建 store/index.ts(src目录下新建store文件夹,并创建index.ts文件)

import { createPinia } from 'pinia'
import piniaPluginPersist from 'pinia-plugin-persist'

const store = createPinia()
store.use(piniaPluginPersist)

export default store


3-2、在main.js中引用

import { createApp } from 'vue'

import App from './App.vue'

import store from './store'

const app = createApp(App)
app.use(store)
app.mount('#app')

3-3、新建 store/modules(store文件夹下新建modules文件夹,并创建xxx.ts文件)

import { defineStore } from 'pinia'

export const userStore = defineStore('qa', {
  state: () => {
    return {
      a: 1
    }
  },
  getters: {
    getQaDetails(state) {
      return state.a
    }
  },
  actions: {
    setQaDetails(i: number) {
      this.a = i
    }
  },
  persist: {
    key: 'storekey', // 修改存储的键名,默认为当前 Store 的 id
    storage: window.localStorage // 存储位置修改为 sessionStorage或localStorage
  }
})

使用方法

WeChat42e1a46c0a62c51ce66ee9f1d48f3eb3.jpg

4、配置环境

项目根目录新建:.env.development :

   VITE_APP_CURRENTMODE = development 
   VITE_APP_WEB_URL= 'YOUR WEB URL'

项目根目录新建:.env.production :

   VITE_APP_CURRENTMODE = production 
   VITE_APP_WEB_URL= 'YOUR WEB URL'

项目根目录新建:.env.mock :

   VITE_APP_CURRENTMODE = mock 
   VITE_APP_WEB_URL= 'http://localhost:8080'

组件中使用:

console.log(import.meta.env.VITE_APP_WEB_URL)

配置 package.json打包区分开发环境和生产环境:

"dev-mock": "vite --mode mock",
"dev": "vite --mode development",
"build:dev": "vite build --mode development", 
"build:pro": "vite build --mode production",

5、路由

//安装路由
yarn add vue-router

新建 router/index(src文件夹下新建router文件夹下新建index.ts

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
const routes: RouteRecordRaw[] = [
  {
    path: '/',
    name: 'login',
    component: () => import('@/views/login/Login.vue') // 注意这里要带上 文件后缀.vue
  }
]
const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

修改入口文件 mian.ts :

import router from './router/index'

app.use(router)

6、保存的时候自动修复代码格式

.vscode新建 settings.json

{
  // 开启自动修复
  "editor.codeActionsOnSave": {
    "source.fixAll": true
  },
  // 保存的时候自动格式化
  "editor.formatOnSave": true,
  // 默认格式化工具选择prettier
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "stylelint.validate": ["vue"],
  "vue.codeActions.enabled": false // Add "vue" language.
}

7、安装css第三方库(tailwindcss)

yarn add -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

找到tailwind.config.js文件加入下方代码

/** @type {import('tailwindcss').Config} */
export default {
  content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
  theme: {
    extend: {}
  },
  plugins: []
}

src文件夹下找到或新建style.css加入下方代码

@tailwind base;
@tailwind components;
@tailwind utilities;

main.ts中引入style.css文件夹

import './style.css'

WeChat01d14b6513ab4217547c9048cfac2eac.jpg

WeChat6ad3e7ea8296aff837d8369f00dfcdf9.jpg

8、配置 css 预处理器 scss

安装

    yarn add dart-sass --dev 
    yarn add sass --dev

在 src/assets 下新增 style 文件夹,用于存放全局样式文件

新建 main.scss, 设置一个用于测试的颜色变量 :

$test-color: red;

如何将这个全局样式文件全局注入到项目中呢?配置 Vite 即可:

css:{ 
    preprocessorOptions:{
        scss:{ 
            additionalData:'@import "@/assets/style/mian.scss";' 
        } 
    } 
},

组件中使用

不需要任何引入可以直接使用全局scss定义的变量

.test{ color: $test-color; }

9、Vite 常用基础配置

基础配置 运行 代理 和 打包 配置

server: { 
    host: '0.0.0.0', 
    port: 3000, 
    open: true, 
    https: false, 
    proxy: {} 
},
  • 生产环境去除 console debugger
build:{ 
    outDir: '打包后的名称',
    minify: 'terser',
    terserOptions: { 
        compress: { 
            drop_console: true, 
            drop_debugger: true 
        } 
    } 
}
  • 生产环境生成 .gz 文件
// 安装 
yarn add --dev vite-plugin-compression
  • plugins 中添加:
import viteCompression from 'vite-plugin-compression'

// gzip压缩 生产环境生成 .gz 文件 
viteCompression({ 
    verbose: true, 
    disable: false, 
    threshold: 10240, 
    algorithm: 'gzip', 
    ext: '.gz', 
 }),
  • 支持本地svg和网络svg渲染
// 安装
yarn add vite-svg-loader -D
  • plugins 中添加:
import svgLoader from 'vite-svg-loader'

svgLoader(),
  • 一个轻量级的进度条组件Nprogress,路由加载时进度条)

参考此文

  • mock数据配置
// 安装
yarn add mockjs 
yarn add vite-plugin-mock -D
  • plugins 中添加:
import { viteMockServe } from 'vite-plugin-mock'

viteMockServe({ 
    supportTs:true, //打开后,可以读取 ts 文件模块。 请注意,打开后将无法监视.js 文件
    localEnabled: true, //设置是否启用本地 xxx.ts 文件,不要在生产环境中打开它.设置为 false 将禁用 mock 功能
    mockPath: "./src/mock/", //mock文件夹的路径 
    logger: false, //是否在控制台显示请求日志
})
  • mock接口数据(./src/mock/index.ts)
import { MockMethod } from "vite-plugin-mock"
export default [
    {
        url: "/api/invoices",
        method: "get",
        statusCode: 200,
        response: () => {
            return {
                project_id: "abcv1234567890",
            };
        },
    },
    {
        url: "/api/invoices",
        method: "post",
        statusCode: 201,
        timeout: 1000,
        response: () => {
            return {};
        },
    },
] as MockMethod[];

最终 vite.config.ts

import { defineConfig } from 'vite' 
import vue from '@vitejs/plugin-vue' 
import svgLoader from 'vite-svg-loader'
import path from 'path' 
//@ts-ignore 
import viteCompression from 'vite-plugin-compression'

// https://vitejs.dev/config/ 
export default defineConfig({ 
    base: './', //打包路径 
    // 配置别名 
    resolve: { 
        alias: { 
            '@': path.resolve(__dirname, 'src'),
        },
    }, 
    plugins: [ 
        vue(), 
        svgLoader(),
        // gzip压缩 生产环境生成 .gz 文件 
        viteCompression({ 
            verbose: true, 
            disable: false, 
            threshold: 10240, 
            algorithm: 'gzip', 
            ext: '.gz', 
        }), 
        viteMockServe({ 
            supportTs:true, //打开后,可以读取 ts 文件模块。 请注意,打开后将无法监视.js 文件 
            localEnabled: true, //设置是否启用本地 xxx.ts 文件,不要在生产环境中打开它.设置为 false 将禁用 mock 功能 
            mockPath: "./src/mock/", //mock文件夹的路径 
            logger: false, //是否在控制台显示请求日志 
        })
    ], 
    css:{ 
        preprocessorOptions:{ 
            scss:{ 
                additionalData:'@import "@/assets/style/mian.scss";'
            } 
        }
    },
    //启动服务配置 
    server: { 
        host: '0.0.0.0', 
        port: 8000, 
        open: true, 
        https: false, 
        proxy: {} 
    }, 
    // 生产环境打包配置 //去除 console debugger 
    build: { 
        outDir: '打包后的名称',
        minify: 'terser',
        terserOptions: { 
            compress: { 
                drop_console: true, 
                drop_debugger: true, 
            }, 
        },
    }, 
})