vite + vue3 + ts + pinia 使用记录

2,676 阅读4分钟

Vue3 已经在 2022 年 2 月 7 日 成为新的默认版本!尤大在自己的文章中提到了这些:

image.png 之前的项目是vue cli搭建的,在此也将项目做个升级~

Vue官方的项目脚手架工具

npm init vue@latest

然后安装命令行提示进行选择

 Project name:  <your-project-name>
 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 Cypress for testing?  No / Yes

Scaffolding project in ./<your-project-name>...
Done.

通过选择是否开启某个功能,你的vue项目就创建好了。

接下来,通过Vite创建vue-ts项目,安装项目中的工具及配置,更清楚的了解和使用它们:

初始化项目

# npm 6.x
npm init vite@latest my-vue-app --template vue-ts

# npm 7+, 需要额外的双横线:
npm init vite@latest my-vue-app -- --template vue-ts

# pnpm
pnpm create vite my-vue-app -- --template vue-ts

我选用的是 pnpm,创建非扁平化的node_modules,对比npm能够避免一些错误:

  1. 依赖结构的不确定性。
  2. 扁平化算法本身的复杂性很高,耗时较长。
  3. 项目中仍然可以非法访问没有声明过依赖的包。 如果你想了解更详细的对比,推荐一篇文章写的挺详细,关于现代包管理器的深度思考——为什么现在我更推荐 pnpm 而不是 npm/yarn?
my-vue-app
├── public
│   └── favicon.ico
├── src
│   ├── App.vue
│   ├── assets
│   │   └── logo.png
│   ├── components
│   │   └── HelloWorld.vue
│   ├── env.d.ts
│   └── main.ts
├── index.html
├── package.json
├── README.md
├── tsconfig.json
└── vite.config.ts

代码格式化

生成的模板比较简单,我们可以丰富它,添加格式化插件,便于代码格式的统一。

eslint

pnpm add eslint -D
pnpx eslint --init

image.png 完成后会在项目中生成.eslintrc.js文件。在vscode安装eslint插件后,会有错误提示:

image.png 是因为eslint默认不会解析vue文件,因此我们需要添加vue-eslint-parser来解决问题。

module.exports = {
    "env": {
        "browser": true,
        "es2021": true,
        "node": true,
        'vue/setup-compiler-macros': true,
    },
    // 扩展规则
    "extends": [
        "eslint:recommended",
        "plugin:vue/vue3-recommended",
        "plugin:@typescript-eslint/recommended"
    ],
    // 解析器
    "parser":"vue-eslint-parser",
    // 解析器配置项
    "parserOptions": {
        "ecmaVersion": "latest",
        "parser": "@typescript-eslint/parser",
        "sourceType": "module"
    },
    // 规则插件
    "plugins": [
        "vue",
        "@typescript-eslint"
    ],
    "rules": {
    }
}

其中plugins和extends会被混淆,这里说一下理解:

  • plugins 是eslint的插件,配置项中的vue是插件名,默认会省略前缀eslint-plugin-, 在node_modules中可以找到包eslint-plugin-vue,该插件中定义了一些规则,可以直接在extends中使用的规则配置:

image.png 需要在rules、extends中定义后才会生效。

  • extends 其中,可以引用别人写好的完整的配置规则,如需配置prettier,也会省略前缀eslint-config-, 在node_modules中可以找到包eslint-config-prettier,或者也可以使用plugin中的规则,如extends数组中的plugin:vue/vue3-recommended,我们可以在上面的图中找到,可以理解为应用的规则是eslint-plugin-vue插件中configs中的vue3-recommended。

主要在extends中配置,注意先后顺序,如果需要修改规则,在rules中添加,必须是插件中已经自定义的规则,才会生效。

prettier

eslint负责代码校验,prettier负责代码美化。

pnpm add prettier eslint-plugin-prettier eslint-config-prettier -D

其中eslint-config-prettier是为了解决两者之前的冲突。 安装完成需要在.eslintrc.js中的extends中添加配置:

extends: [
    'eslint:recommended',
    'plugin:vue/vue3-recommended',
    'plugin:@typescript-eslint/recommended',
  + 'plugin:prettier/recommended',
  ],

stylelint

对样式文件进行格式化校验

pnpm add stylelint stylelint-config-standard -D

添加.stylelintrc.js文件,并添加配置:

module.exports = {
  extends: ['stylelint-config-standard'],
  rules: {
    'no-descending-specificity': null,
    'selector-pseudo-element-no-unknown': [
      true,
      {
        ignorePseudoElements: ['v-deep'],
      },
    ],
    'selector-pseudo-class-no-unknown': [
      true,
      {
        ignorePseudoClasses: ['deep'],
      },
    ],
  },
};

安装vscode插件

安装 eslintstylelint 插件,保存时自动格式化,需要在配置项中加入

"editor.codeActionsOnSave": {
    "source.fixAll": true
},
"eslint.alwaysShowStatus": true,
"stylelint.validate": [
    "css",
    "less",
    "postcss",
    "sass",
    "scss"
],

代码提交校验

husky

husky是git hook工具,我们主要用到其中的两个钩子,是进行git操作时会触发的脚本,例如:提交的时候会触发pre-commit钩子,输入提交信息会触发commit-msg钩子。

lint-staged

lint-staged是git暂存区的校验工具,此时我们可以自定义一下操作,运行脚本来检测待提交的代码是否规范。

pnpm add husky lint-staged -D

安装完成后执行

npx husky install

image.png

  • commit-msg 提交信息校验 采用自定义校验规则的方式
npx husky add .husky/commit-msg 'node .husky/commit-lint.js $1'

添加commit-lint.js文件

image.png

  • pre-commit 提交代码格式化
npx husky add .husky/pre-commit "npx --no-install lint-staged"

在package.json中添加

"lint-staged": {
    "*.md": "prettier --write",
    "*.{css,less}": "stylelint --fix",
    "*.{js,vue,ts,jsx,tsx}": [
      "eslint --fix",
      "prettier --write"
    ]
}

可以进行开发了。

配置文件别名

在vite.config.ts中添加alias

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': resolve(__dirname, 'src'),
      store: resolve(__dirname, 'src/store'),
      components: resolve(__dirname, 'src/components'),
    },
  },
});

还需要在tsconfig.json添加,

"baseUrl": ".",
"paths": {
  "@/*": ["src/*"],
  "store/*": ["src/store/*"],
  "components/*": ["src/components/*"],
}

保证项目中文件正常引用及跳转。

pinia替换vuex

为什么使用 pinia 呢,用起来的感觉和vuex相似,但是简单轻量,很顺滑。

  • 不存在mutations,最初是为了vue-devtools集成,但现在不需要了,现在actions同时支持同步和异步。
  • 不需要进行复杂的配置来支持typescript,一切都是类型化的,并且API的设计方式是尽可能利用TS类型推断。
  • 不再有modules的嵌套结构,你仍然可以在一个store中导入和使用其他一个store来隐式嵌套stores

安装

pnpm add pinia

创建store

  • index.ts
import { createPinia } from 'pinia';

const store = createPinia();

export default store;
  • user.ts
import { defineStore } from 'pinia';

interface UserState {
  name: string;
  sex: string;
  age: number;
}

export const useUserStore = defineStore({
  id: 'user', // id必填,且需要唯一
  state: (): UserState => {
    return {
      name: '张三丰',
      sex: '男',
      age: 10,
    };
  },
  getters: {
    realAge(state) {
      return state.age * 10;
    },
  },
  actions: {
    setInfo({ name, sex, age }: UserState) {
      // 直接通过this修改state
      // this.name = name;
      // this.sex = sex;
      // this.age = age;
      
      // or 批量更新state
      this.$patch({
        name,
        sex,
        age,
      });
    },
  },
});

使用store

<template>
  <h1>{{ msg }}</h1>
  <button type="button" @click="handleClick">click</button>
  <p>name:{{ name }}</p>
  <p>sex:{{ sex }}</p>
  <p>age:{{ realAge }}</p>
</template>

<script setup lang="ts">
import { storeToRefs } from 'pinia';
import { useUserStore } from 'store/user';

defineProps<{ msg: string }>();

const userStore = useUserStore();
// 为避免解构时失去响应性
const { name, sex, realAge } = storeToRefs(userStore);

const handleClick = () => {
  userStore.setInfo({
    name: '花木兰',
    sex: '女',
    age: 2,
  });
};
</script>

<style scoped></style>

页面展示效果: image.png

在vue-devtools中查看store状态:

image.png

打包及预览

当你构建完成应用后,你可能需要找到 dist 文件夹下找到index.html,在浏览器中运行,现在你可以通过运行 npm run preview 命令,在本地测试该应用。

前提是已经构建,已输出到 dist 文件夹中。

$ npm run build
$ npm run preview

vite preview 命令会在本地启动一个静态 Web 服务器,将 dist 文件夹运行在 http://localhost:5000。这样在本地环境下查看该构建产物是否正常可用就方便了。

UI框架

Element Plus 正式版发布啦!

image.png Element Plus 使用 TypeScript 与 Vue 3.2 开发,提供完整的类型定义文件。并使用 Composition API 降低耦合,简化逻辑。

可以开心的使用了。。。