vue3+ts+vite项目搭建

初始化项目

使用vite脚手架模板创建项目,这里我使用pnpm作为包管理工具

arduino 复制代码
# pnpm
pnpm create vite my-vue-app --template vue
bash 复制代码
cd my-vue-app
pnpm install

得到基础项目目录

安装eslint进行语法检测

csharp 复制代码
pnpm add -D eslint

执行eslint初始化命令

csharp 复制代码
npx eslint --init

根目录新建.eslintignore文件,配置eslint校验范围,这样只会校验src下的ts/js/vue文件

css 复制代码
**/*.ts
**/*.js
**/*.vue

!src/**/*.ts
!src/**/*.js
!src/**/*.vue

安装prettier规范代码风格

css 复制代码
pnpm add --save-dev --save-exact prettier eslint-config-prettier eslint-plugin-prettier

由于eslint和prettier规则可能存在冲突,需要安装eslint-config-prettier和eslint-plugin-prettier 在根目录新建.prettierrc.json配置文件,进行prettier规则配置(可按个人喜好进行配置)

json 复制代码
{
  "printWidth": 80,
  "tabWidth": 2,
  "useTabs": false,
  "singleQuote": true,
  "semi": true,
  "trailingComma": "none",
  "bracketSpacing": true,
  "endOfLine": "auto"
}

同时在eslint配置文件的extends的末尾加入一行

此时我们检测一下前面步骤是否成功,打开App.vue文件,如果看到ts代码后面因为没有分号eslint标红了,说明prettier和eslint的代码风格检查生效了,此时按ctrl+s保存文件,如果自动格式化添加";"了,说明我们都配置成功了

安装husky和lint-stage

husky 包含很多git hook(钩子),常用有:pre-commit、commit-msg、pre-push。类似于生命周期的概念,可以在我们进行git操作的不同时期执行相应命令。
lint-staged 这个工具一般结合 husky 来使用,它可以让 husky 的 hook 触发的命令只作用于 git add 那些文件(即 git 暂存区的文件),而不会影响到其他文件。

sql 复制代码
pnpm add --save-dev husky lint-staged  

初始化husky

csharp 复制代码
npx husky init

此时根目录下多了一个.husky文件夹,里面有个pre-commit文件,在里面写入

bash 复制代码
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged

在package.json中增加lint-staged配置

安装commitlint校验提交信息格式

bash 复制代码
npm install @commitlint/cli @commitlint/config-conventional -D

在根目录下新建.commitlintrc.json文件,定义提交信息格式

perl 复制代码
{
  "extends": [
    "@commitlint/config-conventional"
  ]
}

在.husky文件夹下新建commit-msg文件,添加hook钩子,添加以下代码

bash 复制代码
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx --no-install commitlint --edit $1

配置别名

配置别名要修改ts配置和vite配置,为防止node的中的变量被ts报错,需要安装node的类型

sql 复制代码
pnpm add -D @types/node

配置tsconfig.json文件,在compilerOptions下面加入如下代码,然后重启vscode,防止ts配置未生效

修改vite.config.ts文件,添加以下代码

安装路由

csharp 复制代码
pnpm add vue-router

在src目录下新建router文件夹,新建index.ts

javascript 复制代码
import { createRouter, createWebHashHistory } from 'vue-router';
import App from '@/App.vue';

// 路由规则
const routes = [
  {
    path: '/',
    component: App,
    children: [
      { path: '', redirect: '/home' },
      {
        path: '/home',
        name: 'home',
        component: () => import('@/views/Home.vue')
      },
      {
        path: '/login',
        name: 'login',
        component: () => import('@/views/Login.vue')
      },
      {
        // vue-router@4的变化,舍弃*通配符
        path: '/:pathMatch(.*)*',
        name: '404',
        component: () => import('@/views/404.vue')
      }
    ]
  }
];

const router = createRouter({
  history: createWebHashHistory(),
  routes
});

export default router;

在main.ts中引入

ini 复制代码
import router from '@/router';

const app = createApp(App);

// 路由
app.use(router);

安装axios

csharp 复制代码
pnpm add axios

在src目录下新建utils/request.ts文件,封装axios

typescript 复制代码
import axios, { AxiosError, AxiosRequestConfig } from 'axios';

interface RESPONSE<T = unknown> {
  code: number;
  msg: string;
  data: T;
}

export const instance = axios.create({
  timeout: 10 * 1000, // 30s超时
  withCredentials: false,
  headers: {
    'Content-Type': 'application/json'
  }
});

instance.interceptors.request.use(
  (config) => {
    // 请求拦截器

    // config.headers.Authorization = XXX;
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

instance.interceptors.response.use(
  ($http) => {
    // 响应拦截器
    const res: RESPONSE = $http.data;
    if (res.code === 0) {
      return $http;
    } else {
      console.log('interceptors code', res.code);
      // 后端的标志位未通过
      return Promise.reject(res.msg);
    }
  },
  (e: AxiosError) => {
    // axios请求未成功,例如出现网络错误
    return Promise.reject(e.message);
  }
);

const request = async <T = unknown>(config: AxiosRequestConfig): Promise<T> => {
  const $http = await instance.request<RESPONSE<T>>(config);
  const res = $http.data;

  return res.data;
};

export default request;

安装pinia

csharp 复制代码
pnpm add pinia

在src目录下新建store/index.ts,文件,定义store

typescript 复制代码
// src/store/index.ts
import { defineStore } from 'pinia';
import { createPinia } from 'pinia';

interface GlobalState {
  token: string;
  userInfo: unknown;
}

// defineStore 调用后返回一个函数,调用该函数获得 Store 实体
export const GlobalStore = defineStore({
  id: 'GlobalState', // id: 必须的,在所有 Store 中唯一
  // state: 返回对象的函数
  state: (): GlobalState => ({
    token: '',
    userInfo: {}
  }),
  getters: {},
  actions: {
    // 不使用箭头函数
    setToken(token: string) {
      this.token = token;
    },
    setUserIngo(userInfo: unknown) {
      this.userInfo = userInfo;
    }
  }
});

const pinia = createPinia();

export default pinia;

在main.ts中引入

javascript 复制代码
import store from '@/store/index';

app.use(store);

安装Less

csharp 复制代码
pnpm add -D less less-loader

在src目录下新建style目录,在style目录下新建global.less、reset.less、variable.less文件,global定义全局样式,variable定义全局样式变量,reset重置浏览器默认样式,抹平浏览器样式差异。

ruby 复制代码
// reset.less
// 直接复制https://meyerweb.com/eric/tools/css/reset/
less 复制代码
// variable.less 根据自身需要定义变量

@color-text: #4e5969;
@color-background: #e5e6eb;
css 复制代码
// global.less
@import url('./reset.less');

* {
  font-weight: 400;
  font-size: 14px;
  font-family: 'Noto Sans SC';
}

::-webkit-scrollbar {
  width: 6px;
  height: 6px;
  background-color: transparent;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: #b7bdcb;
  border-radius: 3px;
  box-shadow: 4px 4px 15px rgb(112 124 151 / 5%),
    2px 2px 10px rgb(112 124 151 / 10%), 1px 1px 50px rgb(112 124 151 / 15%);
}

::-webkit-scrollbar-thumb:hover {
  background-color: rgb(245 238 238 / 100%);
  border-radius: 3px;
  box-shadow: inset 0 0 6px rgb(0 0 0 / 30%);
}

在vite.config.ts中配置css预处理器,定义变量

dart 复制代码
export default defineConfig({
  // ...
  css: {
    preprocessorOptions: {
      less: {
        additionalData: `@import "${resolve(__dirname, 'src/assets/style/variable.less')}";`
      }
    }
  }
});

在main.ts中引入全局样式

arduino 复制代码
import '@assets/style/global.less';
相关推荐
sunshine64117 分钟前
【CSS】实现tag选中对钩样式
前端·css·css3
真滴book理喻40 分钟前
Vue(四)
前端·javascript·vue.js
蜜獾云42 分钟前
npm淘宝镜像
前端·npm·node.js
dz88i843 分钟前
修改npm镜像源
前端·npm·node.js
Jiaberrr1 小时前
解锁 GitBook 的奥秘:从入门到精通之旅
前端·gitbook
顾平安2 小时前
Promise/A+ 规范 - 中文版本
前端
聚名网2 小时前
域名和服务器是什么?域名和服务器是什么关系?
服务器·前端
桃园码工2 小时前
4-Gin HTML 模板渲染 --[Gin 框架入门精讲与实战案例]
前端·html·gin·模板渲染
不是鱼2 小时前
构建React基础及理解与Vue的区别
前端·vue.js·react.js
沈剑心2 小时前
如何在鸿蒙系统上实现「沉浸式」页面?
前端·harmonyos