目录
初始化项目架构
一步一步搭建自己的Vue3 h5项目架构
备注:文档编写时间为 2023-8-8 注意依赖版本!
项目源码👇👇👇
技术栈
工具类
- NodeJs V16.20.0
- Npm V8.19.4
- Vite V4.4.8
- Eslint V8.45.0
- TypeScript V5.0.2
- Vscode
环境
- Vue V3.3.4
- vue-router V4.2.4
- Vuex V4.0.2
- axios V1.4.0
搭建流程
初始化项目
yarn create vite my-vue-app --template vue-ts
初始化git
cd my-vue-app
git init
git add .
git commit -m "init"
运行项目
yarn
yarn dev
配置 server环境
vite.config.ts
// vite.config.ts
...
base: "./", // 打包路径
server: {
port: 9999, // 服务端口号
open: true, // 服务启动时是否自动打开浏览器
cors: true, // 允许跨域
host: "192.168.7.52" // 本机的局域网IP
}
...
配置项目环境
增加三个文件
修改package.json脚本
...
"scripts": {
"dev": "vite --mode dev",
"test": "vue-tsc && vite build --mode test",
"build": "vue-tsc && vite build --mode prot",
"preview": "vite preview"
},
...
如何使用
import.meta.env.VITE_BASE_URL
重新启动
yarn dev
配置 Eslint
***配置完成 Eslint 最好重新启动 Vscode!!!
yarn add -D eslint vite-plugin-eslint
yarn add -D eslint-plugin-vue
yarn add -D @typescript-eslint/eslint-plugin
yarn add -D @typescript-eslint/parser
增加文件 .eslintrc.cjs
具体文件在末尾
对 vite.config.ts 修改
***配置完成 Eslint 最好重新启动 Vscode!!!
import eslint from "vite-plugin-eslint";
// vite.config.ts
plugins: [vue(), eslint()],
重新启动
yarn dev
增加vue-router
yarn add vue-router@4
App.vue
<!-- src/App.vue -->
<template>
<router-view />
</template>
router
// src/router/index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
import Home from "../pages/home/index.vue";
const routes: Array<RouteRecordRaw> = [
{
path: "/",
name: "Home",
component: Home,
meta: {
title: "首页"
}
}
];
const router = createRouter({
history: createWebHistory(),
routes
});
export default router;
home
<!-- src/pages/home/index.vue -->
<template>
<p>home</p>
</template>
<script lang="ts" setup></script>
<style scoped></style>
main.ts引用 router
// ...
import router from "./router";
createApp(App).use(router).mount("#app");
重新启动
yarn dev
配置 src/@ 别名
对 vite.config.ts 修改
// vite.config.ts
import path from "path";
declare const __dirname: string;
// ...
resolve: {
alias: {
"@": path.resolve(__dirname, "src")
}
},
// ...
对 tsconfig.ts 修改
"compilerOptions":{
"baseUrl": ".",
"paths": {
"@/*": [
"src/*"
]
},
}
// ...
使用 @
// src/router/index.ts
// ...
import Home from "@/pages/home/index.vue";
// ...
关于类型设计
以模块的形式
对 tsconfig.ts修改
// 新增 typings/**/*.ts
// ...
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "typings/**/*.ts"],
// ...
增加axios
官方文档介绍比较详细,点击下方👇👇👇
***简单的http封装(文章末尾)
关于接口设计
接口设计思路,以模块的形式,比如 user是一个模块,商品是一个模块,订单是一个模块 目录结构 👇👇👇
.eslintrc.cjs
module.exports = {
env: {
browser: true,
es2021: true
},
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:vue/vue3-essential"
],
overrides: [
{
env: {
node: true
},
files: [".eslintrc.{js,cjs}"],
parserOptions: {
sourceType: "script"
}
}
],
parser: "vue-eslint-parser", // 新增
parserOptions: {
ecmaVersion: "latest",
parser: "@typescript-eslint/parser",
sourceType: "module"
},
plugins: ["@typescript-eslint", "vue"],
rules: {
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off", //生产模式不允许使用log
"no-debugger": "error", //生产默认不允许使用debugger
"@typescript-eslint/no-explicit-any": "off",
"vue/multi-word-component-names": "off",
"vue/no-mutating-props": "off",
"@typescript-eslint/no-unused-vars": "error",
"generator-star-spacing": "off",
indent: "off",
"space-before-function-paren": "off",
"vue/html-end-tags": "error", //标签必须闭合
camelcase: "error", // 强制驼峰法命名
eqeqeq: "error", // 要求使用 === 和 !==
"no-eq-null": "error", // 禁止对null使用==或!=运算符
"no-extra-parens": "error", // 禁止非必要的括号
"no-extra-semi": "error", // 禁止多余的冒号
"no-invalid-regexp": "error", // 禁止无效的正则表达式
"no-multi-spaces": "error", // 不能用多余的空格
"vue/require-v-for-key": "error", // vue的for循环是否必须有key
"no-var": "off", // 禁用var,用let和const代替
"no-self-compare": "error", // 不能比较自身
"no-redeclare": "error", // 禁止重复声明变量
quotes: [2, "double"], // 必须使用双引号
semi: [2, "always"], // 语句强制分号结尾
"comma-dangle": [2, "never"], // 数组和对象键值对最后一个逗号, never参数:不能带末尾的逗号, always参数:必须带末尾的逗号
"no-undef": "off"
}
};
axios简单封装
// src/tools/http.ts
import axios from "axios";
// 创建 axios 实例
const service = axios.create({
/* 基础地址 一般都是动态的 */
baseURL: GLOBAL_API_URL,
/* 请求类型定义 */
// headers: {
// 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
// },
/* 如果用的JSONP,可以配置此参数带上cookie凭证,如果是代理和CORS不用设置 */
withCredentials: false,
/* 请求超时时间 */
timeout: 6000
});
/**
* http request 拦截器
*/
service.interceptors.request.use(
(config) => {
const token = localStorage.getItem("szd_token"); /* 获取token */
if (token) {
/* 让每个请求携带自定义 token 请根据实际情况自行修改 */
config.headers["token"] = `${token}`;
}
if (config.method === "get") {
/* 让每个请求都携带一个不同的时间参数,防止浏览器缓存不发送请求 */
config.params = {
...config.params
};
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
/**
* http response 拦截器
*/
service.interceptors.response.use(
(response) => {
return response.data;
},
(error) => {
console.log("请求出错:", error);
}
);
export default service;