# vue3-quickstart **Repository Path**: xkrumeng/vue3-quickstart ## Basic Information - **Project Name**: vue3-quickstart - **Description**: vue3 + vite + typescript + eslint + jest 项目配置 - **Primary Language**: JavaScript - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 5 - **Forks**: 1 - **Created**: 2020-12-18 - **Last Updated**: 2022-10-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # vue3 + vite + typescript 项目 ## 1. 项目初化 ```bash # 全局安装vite-app npm i -g vite-app # 创建项目 yarn create vite-app # 或者 npm init vite-app # 进入项目,安装依赖 cd yarn # 或 npm i # 运行项目 yarn dev # 打开浏览器 http://localhost:3000 查看 ``` ## 2. 引入TypeScript ```bash # 加入ts依赖 yarn add --dev typescript ``` 在 项目根目录下创建typescript的配置文件 **tsconfig.json** ```json { "compilerOptions": { // 允许从没有设置默认导出的模块中默认导入。这并不影响代码的输出,仅为了类型检查。 "allowSyntheticDefaultImports": true, // 解析非相对模块名的基准目录 "baseUrl": ".", "esModuleInterop": true, // 从 tslib 导入辅助工具函数(比如 __extends, __rest等) "importHelpers": true, // 指定生成哪个模块系统代码 "module": "esnext", // 决定如何处理模块。 "moduleResolution": "node", // 启用所有严格类型检查选项。 // 启用 --strict相当于启用 --noImplicitAny, --noImplicitThis, --alwaysStrict, // --strictNullChecks和 --strictFunctionTypes和--strictPropertyInitialization。 "strict": true, // 生成相应的 .map文件。 "sourceMap": true, // 忽略所有的声明文件( *.d.ts)的类型检查。 "skipLibCheck": true, // 指定ECMAScript目标版本 "target": "esnext", // 要包含的类型声明文件名列表 "types": [ ], "isolatedModules": true, // 模块名到基于 baseUrl的路径映射的列表。 "paths": { "@/*": [ "src/*" ] }, // 编译过程中需要引入的库文件的列表。 "lib": [ "ESNext", "DOM", "DOM.Iterable", "ScriptHost" ] }, "include": [ "src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "tests/**/*.ts", "tests/**/*.tsx" ], "exclude": [ "node_modules" ] } ``` 在 ***src*** 目录下新加 **shim.d.ts** 文件 ```typescript /* eslint-disable */ import type { DefineComponent } from 'vue' declare module '*.vue' { const component: DefineComponent<{}, {}, any> export default component } ``` 把 **main.js** 修改成 **main.ts** 在根目录,打开**Index.html** ```html 修改为: ``` ## 3. 引入eslint ```bash # 安装eslint prettier 依赖 # @typescript-eslint/parser @typescr ipt-eslint/eslint-plugin 为eslint对typescript支持 yarn add --dev eslint prettier eslint-config-prettier eslint-plugin-prettier eslint-plugin-vue @typescript-eslint/parser @typescr ipt-eslint/eslint-plugin ``` 在根目录下建立eslint配置文件: **.eslintrc.js** ```js module.exports = { parser: 'vue-eslint-parser', parserOptions: { parser: '@typescript-eslint/parser', ecmaVersion: 2020, sourceType: 'module', ecmaFeatures: { jsx: true } }, extends: [ 'plugin:vue/vue3-recommended', 'plugin:@typescript-eslint/recommended', 'prettier/@typescript-eslint', 'plugin:prettier/recommended' ], rules: { '@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', // 'no-use-before-define': [ // 'error', // { // functions: false, // classes: true, // }, // ], '@typescript-eslint/no-use-before-define': 'off', // '@typescript-eslint/no-use-before-define': [ // 'error', // { // functions: false, // classes: true, // }, // ], '@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: '^h$', varsIgnorePattern: '^h$' } ], 'no-unused-vars': [ 'error', { argsIgnorePattern: '^h$', varsIgnorePattern: '^h$' } ], 'space-before-function-paren': 'off', quotes: ['error', 'single'], 'comma-dangle': ['error', 'never'] } }; ``` 建立**prettier.config.js** ```js module.exports = { printWidth: 100, tabWidth: 2, useTabs: false, semi: false, // 未尾逗号 vueIndentScriptAndStyle: true, singleQuote: true, // 单引号 quoteProps: 'as-needed', bracketSpacing: true, trailingComma: 'none', // 未尾分号 jsxBracketSameLine: false, jsxSingleQuote: false, arrowParens: 'always', insertPragma: false, requirePragma: false, proseWrap: 'never', htmlWhitespaceSensitivity: 'strict', endOfLine: 'lf' } ``` ## 4. 引入jest 测试 ```bash yarn add --dev @babel/core @babel/preset-env @testing-library/jest-dom @types/jest @vue/test-utils@next babel-jest jest ts-jst vue-jest@next ``` 创建**jest.config.js** ```js const path = require('path') module.exports = { rootDir: path.resolve(__dirname), clearMocks: true, coverageDirectory: 'coverage', coverageProvider: 'v8', moduleFileExtensions: ['vue', 'js', 'json', 'jsx', 'ts', 'tsx', 'node'], // 别名设置 moduleNameMapper: { '@/(.*)$': '/src/components/$1' }, preset: 'ts-jest', testEnvironment: 'jsdom', // 测试文件 testMatch: ['/tests/unit/*.spec.ts?(x)'], transform: { '^.+\\.vue$': 'vue-jest', '^.+\\js$': 'babel-jest', '^.+\\.(t|j)sx?$': 'ts-jest' } } ``` 新建测试用例文件 **test/unit/HelloWorld.spec.ts** ```typescript import { mount } from '@vue/test-utils' import HelloWorld from '@/HelloWorld.vue' test('displays message', async () => { const wrapper = await mount(HelloWorld) // Assert the rendered text of the component expect(wrapper.find('p').text()).toBe('0') await wrapper.find('button').trigger('click') expect(wrapper.find('p').text()).toBe('1') }) ``` 在 **package.json** 命令(*scripts*)中加入 "test": "jest" 。 如下: ```json "scripts": { "dev": "vite", "build": "vite build", "test": "jest" }, ``` 运行 **yarn test** 查看测试结果 ## 5. 加入vue-router、vuex ```bash yarn add vue-router@next vuex@next ``` 在根目录下创建 **store/index.ts** ```typescript import { InjectionKey } from 'vue' import { createStore, Store } from 'vuex' export interface State { count: number } export const key: InjectionKey> = Symbol() export const store = createStore({ state() { return { count: 0 } }, mutations: { increment(state) { state.count++ } } }) ``` **main.ts** 修改 ```typescript import { createApp } from 'vue' import { store, key } from './store' import App from './App' import './index.css' const app = createApp(App) app.use(store, key) app.mount('#app') ``` **components/HelloWord.vue** 修改 ```vue ```