VUE3 + elementPlus 项目的工程熟悉及快速开发

203 阅读14分钟

VUE3 + elementPlus 项目的工程熟悉及快速开发

1. 本期视频的目的和意义

这个系列的视频, 是针对有一定 web 开发经验, 非前端开发工程师的小伙伴, 快速了解并上手Vue3 + Vite + ElementPlus前端项目工程

本视频, 将从 前端开发的环境搭建 开始讲起, 依次进行项目搭建, 项目配置, 接口封装及使用, elementPlus 的安装及使用简单介绍, vue-router, 登录页面, 和一个简单的增删改查页面的开发。视频内容不会太深, 但涉及的范围相对比较广

本视频的目的: 目前网上的教程已经很多了也很详细, 如果想从 0 开始学习前端开发, 可以参考其他教程, 或者如果大家想看 UP 主后续也可以出 本期视频主要解决的问题是, 针对 web 开发从业者, 快速了解前端项目工程, 并可以临时对项目的 bug 进行修改或者开发一些简单功能

大家有什么建议或者疑问, 欢迎大家在评论区留言或者私信我

2. 前端开发环境搭建

需要: vscode, 良好的网络环境, nvm, Nodejs

2.1 网络环境

建议大家科学上网

2.2 简单介绍 Node.js 在前端开发中的作用

Node.js 在前端开发中扮演着非常重要的角色, 尽管它本身是一个运行在服务器端的 JavaScript 运行环境。下面我将为你介绍一些 Node.js 在前端开发中的主要用途:

1. 构建工具和任务自动化

Node.js 生态系统中有许多强大的构建工具和任务自动化工具, 如 Webpack、Gulp、Grunt 等。这些工具依赖于 Node.js 来执行诸如代码压缩、CSS 预处理、模块打包、文件合并等任务。它们可以帮助开发者提高效率, 减少重复劳动。

2. 包管理

npm(Node Package Manager)是 Node.js 默认的包管理器。我们需要 npm 安装、更新、卸载各种前端库和框架, 如 Vue、ElementPlus、axios 等。

3. 开发服务器

前端开发时, 本地通常会使用 Node.js 启动一个开发服务器, 用于做反相代理。

4. 前端脚手架工具

很多流行的前端脚手架工具都是基于 Node.js 实现的, 例如 Vite、Vue CLI 等。这些工具提供了一键生成项目结构的功能, 大大简化了项目的初始化过程, 并且内置了最佳实践配置, 让开发者能够快速上手。

2.2 为什么需要 node 版本管理及 nvm 的安装和简单使用

Node 版本经常升级, 会带来一些新的特性, 同时也可能会对之前版本的 API 做修改, 这就会导致如果使用 node14 版本开发的项目往往在 node18 上无法运行, 反之亦然; 所以往往电脑上会安装不止一个版本的 node, 这时候我们就需要一个 node 版本管理工具——nvm

2.2.1 安装 nvm

MacOS:

$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash

$ wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash

环境变量

export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm

windows: window 版本的名字叫做 NVM for Windows, 推荐大家直接从 github 进去下载安装

2.2.2 nvm 的简单使用 及 Nodejs 的安装
  1. 安装指定版本的 node: 使用 $ nvm install 18, 安装的就是大版本 18 的最新稳定版本

    • 这里安装 18 的原因, 是如果要使用最新版本的 Vite 作为脚手架工具, 必须要用到>= 18Node版本

    • 如果是现成的项目, 具体安装哪个版本, 需要去 package.json中的 engines 字段查看

  2. 查看当前 node 版本: $ node -v

  3. 使用 nvm 单次切换 node 版本: $ nvm use 18

  4. 使用 nvm 指定默认 node 版本: $ nvm alias default 18

  5. 查看当前电脑上已经安装的 node 版本: $ nvm list

  6. 卸载指定的 node 版本: $ nvm uninstall 18

2.2.3 常见问题

安装 node 之后 npm i报错找不到指定的命令

  • 可能原因 1: 当前命令行没有切换到指定 node 版本

    解决方法: 设置默认 node 版本

  • 可能原因 2: 没有设置环境变量

    这个问题可以通过 node -v命令来验证, 请参考上面的 mac 设置环境变量的教程, win 一般不会出现这个情况

  • 可能原因 3: 由于网络情况不好, 没有成功安装 npm

    解决方法: 简单粗暴——重装(一般来说, 使用国内镜像可能会出现这类问题, 又回归到科学上网)

3 Vite + Vue3 项目的搭建及初识项目配置

3.1 vite

  1. 发音: /vit/
  2. vitevue-cli都是 VUE 常用的脚手架, 的区别在于, vite 不需要单独安装, 直接使用, 并且是目前 VUE3 最推荐的实践方式;很多新项目都是使用 Vite 来创建的;所以本次教程只讲 Vite , 如果大家对 vue-cli 感兴趣, 后面再单独出 vue-cli 的教程
3.1.1 创建项目
  1. 创建 vite 项目
    $ npm create vite@latest my-vue-app 注意: my-vue-app 需要替换成你要创建的项目的项目名

  2. 选择模板
    $ Select a framework: 中选择 vue
    $ Select a variant: 中选择 javascript 或者 typescript

  3. 安装依赖并启动项目 这一步我们简单的使用 $ npm i 命令即可安装依赖

注意: 大家在这一步生成项目之后, 可以看一看.gitignore中的内容

3.1.2 初识package.json找到项目启动命令

启动命令:
刚才讲到安装依赖, 接下来告诉大家, 如何查看项目的启动命令

当我们刚建好项目的时候, 启动命令为dev, 我们打开终端, 执行npm run dev即可启动项目

请注意, 我们的项目启动命令是可以自己定义的, 就在 package.json中的 scripts 字段可以查看, 一般来说, 字段值为 vite开头的, 就是项目的启动命令

这段配置的意思是:

  1. 将以 /api为开头的请求, 代理到 VITE_BASE_URL(target字段)对应的地址上

  2. 并且修改原请求将/api替换成空字符串(rewrite字段)

  3. changeOrigin的意思是: 将服务器接收请求的请求头中HOST字段修改为target对应的值

注意, vite 的配置还有很多, 这里只提及了代理服务的配置, 是为了大家能够快速的启动项目, 其他的配置项, 在5.7 简单项目配置章节中详细讲解。

5 VUE3 项目的目录简介

5.1 node_modules

这个目录下的文件不要动, 这是该项目所需要的依赖

5.2 public

这个目录下会放置一些静态资源, 适用于放在public目录下的静态资源包括

  1. 不会被源码引用(例如 robots.txt)
  2. 必须保持原有文件名(没有经过 hash)
  3. ...或者你压根不想引入该资源, 只是想得到其 URL

注意: 应该始终使用根绝对路径来引入 public 中的资源 —— 举个例子, public/icon.png 应该在源码中被引用为 /icon.png

注意: 静态资源的引用, 我会放在后面来讲解, 在 vitewebpack 中, 静态资源的引用有很大的区别(todo)

5.3 src

这个目录下, 放置的就是项目源码, 通常来说, src目录又会分为下面的目录

- src
  - assets: 静态资源目录, 包括图片, icon, 公共样式等
  - components: 公共组件
  - App.vue: 根组件
  - main.j(t)s: 入口文件
  - style.css: 公共样式(这个文件只在初创的时候会有, 但不是项目必须的, 可以删除该文件及其引用)
  - vite-env.d.ts: 补充声明文件(不用管)
  - pages(views): 页面级组件: 路径跟路由配置能对应上
  - router: vue的路由文件
  - utils: 公共工具函数
  - store: vue状态管理工具(有些项目没有)
  - api(server、request)项目接口

大致上来说, 源码文件分为上面几个部分, 在这里只是带着大家一起熟悉一下项目的目录, 后面会有路由, 状态机等的详细的介绍

上面的文件目录为单页应用的目录接口, 多页应用有些差别, 放在后面讲

5.4 再识package.json

在前端开发中, 页面的开发和库的开发, 所常用的 package.json字段有一些区别, 所以, 在这一节中, 会分为web 项目常见字段前端开源库项目常用非前端开发的同学, 可以只看web 常见项目字段

5.4.1 web 项目常见字段

基本信息

  • name: 项目名称。

  • version(可以省略): 版本号, 有助于版本追踪和管理。

    描述与入口(通常省略)

  • description: 简短描述项目用途的信息。

  • main: 指定模块入口点的文件路径。

    脚本命令

  • scripts: 定义了一系列可以在命令行中通过 npm 或 yarn 运行的脚本命令, 如start, build, test等, 启动命令也会定义在这里。

    依赖管理

  • dependencies: 列出所有生产环境下必需的依赖包及其版本范围。

  • devDependencies: 开发环境下的依赖包, 例如构建工具和编译器。

    兼容性

  • browserslist: 配置浏览器兼容性列表, 告知工具你的项目需要支持哪些浏览器。

  • engins: 用于指定你的项目(或包)运行所需的 Node.js 版本以及其他相关工具的版本范围

    其他重要信息

  • repository(经常省略): 包含代码仓库的位置信息。

  • author: 作者信息。

  • license: 开源许可证类型。

    项目隐私设置

  • private: 如果设置为 true, 则该项目不能被发布到 npm 注册表, 防止意外公开私有项目。

注意: 其中scriptsengins 字段最重要, scripts有项目启动、打包的命令, engins会描述需要的 node 版本

示例:

{
  "name": "my-vue-project",
  "version": "0.0.1",
  "description": "这是一个使用Vite和Vue 3构建的示例前端Web项目。",
  "main": "src/main.js",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "serve": "vite preview",
    "lint": "eslint --ext .js,.vue --ignore-path .gitignore --fix src",
    "test:unit": "vitest --environment jsdom"
  },
  "dependencies": {
    "vue": "^3.2.13"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^1.9.3",
    "eslint": "^8.0.0",
    "eslint-plugin-vue": "^8.0.3",
    "vite": "^2.6.4",
    "vitest": "^0.2.0"
  },
  "browserslist": ["> 1%", "last 2 versions", "not dead", "not ie <= 11"],
  "keywords": ["vue", "vite", "frontend"],
  "author": "你的名字 <youremail@example.com>",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/yourusername/my-vue-project.git"
  },
  "bugs": {
    "url": "https://github.com/yourusername/my-vue-project/issues"
  },
  "homepage": "https://github.com/yourusername/my-vue-project#readme"
}
5.4.2 前端开源库项目常用 package.json 字段

keywords: 一个字符串数组, 描述项目的标签或关键词, 有助于在 npm 或其他包管理器中被发现。

bugs: 提供问题追踪系统的 URL 或者电子邮件地址, 方便用户报告错误或提出建议。

homepage: 指定项目的主页 URL, 通常指向 GitHub 仓库、官方网站等。

files: 列出要包含在项目发布版本中的文件或目录, 是一个数组。这对于确保只发布必要的文件非常有用。

publishConfig: 配置发布到 npm 的相关信息, 如注册表 URL 等。

peerDependencies: 定义与你的库一起使用但不由你的库直接安装的依赖项。这通常用于插件或库之间有明确版本兼容性要求的情况。

bundledDependenciesbundleDependencies: 列出需要打包在一起发布的依赖包名称数组。这些依赖不会单独安装, 而是包含在你的发布包中。

module: 指定 ES 模块入口点, 对于支持原生 ES 模块的现代浏览器或工具链很有用。

exports: 更细粒度地控制模块的入口点, 可以为不同的环境(如.js.mjs)指定不同的入口文件, 是未来推荐的方式。

sideEffects: 告知打包工具你的库是否有副作用, 帮助优化 Tree Shaking, 减少最终打包体积。

示例

{
  "name": "my-gulp-frontend-lib",
  "version": "0.0.1",
  "description": "这是一个基于Gulp构建的前端开源库。",
  "main": "dist/index.js",
  "scripts": {
    "build": "gulp build",
    "watch": "gulp watch",
    "lint": "eslint ."
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/yourusername/my-gulp-frontend-lib.git"
  },
  "keywords": ["前端", "库", "工具", "Gulp", "web开发"],
  "author": "作者的名字 <作者的邮箱>",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/yourusername/my-gulp-frontend-lib/issues"
  },
  "homepage": "https://github.com/yourusername/my-gulp-frontend-lib#readme",
  "devDependencies": {
    "gulp": "^4.0.2",
    "gulp-sass": "^5.0.0",
    "gulp-clean-css": "^4.3.0",
    "gulp-uglify": "^3.0.2",
    "gulp-eslint": "^6.0.0",
    "gulp-autoprefixer": "^8.0.0",
    "del": "^6.0.0"
  },
  "dependencies": {
    "lodash": "^4.17.21"
  }
}
5.5 环境变量
5.5.1 简介
  1. 在 vite 项目中.env或者.env.[mode]文件为环境变量的配置文件
  2. 作用是将VITE_开头的变量,注入在你的应用中(vite的默认配置是这样,也可以通过配置修改环境变量的命名方式,这里不做讨论)
  3. 在环境变量最常见的用法,就是配合 devServer 的配置,进行反相代理
5.5.2 使用方法
  1. 在 vite.config.js 中:使用loadEnv方法加载
import { defineConfig, loadEnv } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig(({ command, mode }) => {
  // 加载环境变量,mode代表当前环境模式,process.cwd()获取当前工作目录
  const env = loadEnv(mode, process.cwd(), '');

  return {
    plugins: [vue()],

    // 使用环境变量设置开发服务器端口
    server: {
      port: parseInt(env.VITE_PORT) || 3000, // 从环境变量读取端口号,默认3000
      proxy: {
        '/api': {
          target: env.VITE_API_BASE_URL || 'http://localhost:5000', // 设置代理目标,默认http://localhost:5000
          changeOrigin: true,
          rewrite: path => path.replace(/^\/api/, ''), // 路径重写规则
        },
      },
    },

    // 根据环境变量修改构建输出目录
    build: {
      outDir: env.VITE_OUTPUT_DIR || 'dist', // 输出目录,未指定时默认为'dist'
    },
  };
});
  1. 在项目源码中:使用import.meta.env.
// 引入必要的库,这里假设你正在使用Vue.js和Vite
import { createApp } from 'vue';
import App from './App.vue';

// 注意:通过 Vite 访问环境变量时,必须以 `import.meta.env.` 开头
// 读取应用名称,并设置为页面标题
document.title = import.meta.env.VITE_APP_NAME || '默认应用名称'; // 如果未定义,则使用默认值

const app = createApp(App);

// 将API基础URL挂载到Vue实例上,方便组件内调用
app.config.globalProperties.$apibaseURL = import.meta.env.VITE_API_BASE_URL;

// 挂载应用
app.mount('#app');

.env.development为本地启动项目时加载的环境变量文件
.env.production为项目打包时加载的环境变量文件

注意: 如果将环境变量命名为.env.local, 则很可能不会提交到仓库中, 因为 .gitignore会默认添加这个文件

.env                # 所有情况下都会加载
.env.local          # 所有情况下都会加载, 但会被 git 忽略
.env.[mode]         # 只在指定模式下加载
.env.[mode].local   # 只在指定模式下加载, 但会被 git 忽略

注意: 环境变量的配置是有优先级的
Vite 总是会加载 .env 和 .env.local 文件, 除此之外还会加载模式特定的 .env.[mode] 文件 .env.[mode] > .env

注意: 通常情况下, 只有以 VITE_为开头的环境变量, 才会被识别

注意: 修改环境变量之后, 需要重新启动项目才能使得其生效

5.6 最佳实践
my-vue-app/
├── public/                  # 存放不需要处理的静态资源
├── src/
│   ├── assets/              # 存放图片、样式等资源
│   ├── components/          # 可复用的Vue组件
│   ├── layouts/             # 应用布局
│   ├── router/              # 路由配置
│   ├── store/               # 状态管理(如果使用)
│   ├── views/               # 页面级别的组件
│   ├── utils/               # 工具函数或辅助方法
│   ├── App.vue              # 主组件
│   └── main.js              # 应用入口点
├── .eslintrc.js             # ESLint配置
├── .prettierrc              # Prettier配置
├── vite.config.js           # Vite配置文件
├── package.json             # 项目依赖和脚本
└── README.md                # 项目说明文档

最佳实践指南

  1. 模块化设计

    • 将功能相近的组件、逻辑分组到相应的目录中。
    • components 目录下的组件应尽可能独立且可重用。
  2. 路由懒加载

    • 利用 Vue Router 的懒加载特性来提升首屏加载速度:
const Home = () => import(/* webpackChunkName: "home" */ '../views/Home.vue');
  1. 状态管理

    • 对于复杂应用,考虑使用 Vuex 进行状态管理。
    • 保持 store 中的状态尽可能扁平化,便于管理和调试。
  2. 环境变量

    • 使用 .env 文件配置不同的环境变量。
    • 支持模式特定的环境变量配置,如 .env.development.env.production
  3. 代码格式化与规范检查

    • 集成 ESLint 和 Prettier 来确保代码风格一致性和质量。
    • 设置 pre-commit 钩子,在提交代码之前自动运行 linting 和 formatting 检查。
  4. 测试

    • 为关键业务逻辑编写单元测试和端到端测试。
    • 推荐工具:Vue Test Utils。
  5. 文档和注释

    • 保持良好的代码注释习惯。
    • 编写 README 文档,介绍如何安装、运行以及贡献代码。
  6. 持续集成/持续部署(CI/CD)

    • 配置自动化 CI/CD 流程,简化发布过程并确保代码质量。

通过遵循这些最佳实践,你可以构建一个结构清晰、易于维护和扩展的 Vue 3 + Vite 项目。记得随着项目的成长适时调整项目结构和开发流程。

5.7 简单项目配置

配置示例

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

// 在配置函数外部调用 loadEnv 来加载环境变量
export default defineConfig(({ command, mode }) => {
  // 使用 loadEnv 加载环境变量
  const env = loadEnv(mode, process.cwd(), '');

  // 获取代理目标地址,确保在 .env 文件中定义了 VITE_PROXY_TARGET 变量
  const proxyTarget = env.VITE_PROXY_TARGET;
  return {
    plugins: [
      vue(),
      vueJsx(), // 支持 JSX/TSX
    ],
    resolve: {
      alias: {
        // 定义路径别名,方便引用 src 目录下的资源
        '@': path.resolve(__dirname, 'src'),
      },
    },
    server: {
      port: 3000, // 开发服务器监听端口
      open: true, // 启动时自动打开浏览器窗口
      proxy: {
        // 代理配置,用于解决开发环境下的跨域问题
        '/api': {
          target: proxyTarget, // 从环境变量中读取代理目标地址
          changeOrigin: true, // 修改请求源(Use with request.getHeader("Host") on the server side)
          rewrite: path => path.replace(/^\/api/, ''), // 将前缀 /api 替换为空字符串
        },
      },
    },
    build: {
      outDir: 'dist', // 构建输出目录
      assetsDir: 'assets', // 资源目录名称
    },
    css: {
      preprocessorOptions: {
        scss: {
          // 在此处添加全局的 SCSS 变量或引入文件
          additionalData: `@import "./src/styles/variables.scss";`,
        },
      },
    },
  };
});
5.7.1 代理配置

通过server.proxy可以进行代理配置,除了这里需要配置,也需要在请求封装的时候对baseURL进行配置。这里我们先介绍代理配置,关于baseURL的配置和使用,我们会在6.4 baseURLvite 反向代理章节中详细讲解。

5.7.2 什么是@及路径别名配置

在前端代码中经常看见路径的前面多了一个@, 这个@指的就是路径别名,一般用来指代src目录。配置路径别名的方法如下:

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

export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
      '@components': path.resolve(__dirname, 'src/components'),
      '@views': path.resolve(__dirname, 'src/views'),
      '@assets': path.resolve(__dirname, 'src/assets'),
      '@utils': path.resolve(__dirname, 'src/utils'),
    },
  },
});

注意: 如果是在项目是使用 typescript 开发, 则还需要在tsconfig.json进行以下配置,否则可能出现路径报错的情况

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@components/*": ["src/components/*"],
      "@views/*": ["src/views/*"],
      "@assets/*": ["src/assets/*"],
      "@utils/*": ["src/utils/*"]
    }
  }
}

路径别名的使用

import request from '@/utils/request'
import User from '@/user/index'

const UserForm = () => import ('@components/userForm')

注意:vite 中, 引入图片等静态资源和引入 js模块的方法完全不同, 也不同于之前的 webpack 的方式,后面我们将对引入静态资源的方法做详细解释

5.6.3 dist目录是哪儿来的

在前端开发中,对项目进行打包,回生成一个 dist 目录,这个也是一个默认配置,可以通过如build.outDir进行修改

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

export default defineConfig(({ command, mode }) => {
  // ...
  return {
    // ...
    build: {
      outDir: 'dist', // 构建输出目录
      assetsDir: 'assets', // 资源目录名称
    },
  };
});
5.6.4 部署在域名非根目录下,如何修改配置

Vite 允许你在配置文件中通过 base 字段来设置应用的基础路径。这对于部署到非根目录特别有用。如果你的应用不是部署在域名的根目录(例如,部署在 /yourSubPath/),你需要设置这个属性。使用 './' 可以相对引用资源,适用于大多数情况,特别是 GitHub Pages 等静态站点托管服务

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

export default defineConfig(({ command, mode }) => {
  // ...
  return {
    // ...
    base: './', // 或者 '/yourSubPath/'
  };
});

6 ajaxaxios、接口封装、baseURL及反向代理配置

在这里,我们使用 axios 进行接口的封装,第一步安装npm i axios

6.1 axios简介

打开 axios 的文档,可以看到官网对 axios 的描述,我们这里分成两个部分解读:

  1. axios 是一个基于 promise 网络请求库,作用于 node.js 和浏览器中。
//这句话的意思是,axios 支持 promise 的语法
// 写法 1
const getUserList = () => {
  axios
    .get('/v1/users')
    .then(res => {
      console.log(res);
    })
    .catch(err => console.error(err));
};

//写法 2
const getUserList = async () => {
  try {
    const res = await axios.get('/v1/users');
    console.log(res);
  } catch (err) {
    console.error(err);
  }
};
  1. 在客户端 (浏览端) 则使用 XMLHttpRequests...

6.2 XMLHttpRequestsajaxaxios

  1. 什么是ajax AJAX,全称为"Asynchronous JavaScript and XML"(异步 JavaScript 和 XML),说人话,就是在不更新整个页面的情况下,通过异步的方式更新部分页面内容
  2. ajaxXMLHttpRequests 的关系以及,如何更新 XMLHttpRequest(通常简写为 XHR),是一个浏览器内置对象,它允许 JavaScript 代码执行 HTTP 请求而无需重新加载整个页面,是实现 AJAX(Asynchronous JavaScript and XML)技术的核心之一
const getUserList = () => {
  var xhr = new XMLHttpRequest();
  // 配置它: GET-request for the URL /example/data.json
  xhr.open('GET', '/v1/users', true);
  // 设置状态改变的回调函数
  xhr.onreadystatechange = function () {
    if (xhr.readyState == 4 && xhr.status == 200) {
      // 请求完成且成功
      // 解析JSON响应
      var res = JSON.parse(xhr.responseText);
      console.log(res);
    } else if (xhr.readyState == 4) {
      console.error(xhr.responseText);
    }
  };

  // 发送请求
  xhr.send();
};
  1. axiosXMLHttpRequests的关系 axios的本质,就是对 XMLHttpRequests进行的封装和扩展,可以对比上面的代码,axios 的写法会简单的多

6.3 axios能做什么

基本用法:

// 导入 axios
import axios from 'axios';

// 创建 axios 实例
const request = axios.create({
  // 设置基础 URL
  baseURL: '/api',
  // 设置默认超时时间
  timeout: 5000,
});

// 请求拦截器
request.interceptors.request.use(
  config => {
    // 在发送请求之前做些什么
    // 可以在这里统一设置请求头,比如加入 token 等
    const token = localStorage.getItem('token');
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}`;
    }
    return config;
  },
  error => {
    // 对请求错误做些什么
    return Promise.reject(error);
  }
);

// 响应拦截器
request.interceptors.response.use(
  response => {
    // 对响应数据做点什么
    // 这里可以对返回的数据进行预处理,比如提取 data 字段等
    // 这里 axios 会自动将json 转化成js 对象
    return response.data;
  },
  error => {
    // 对响应错误做点什么
    // 可以根据不同的 HTTP 错误状态码进行不同的处理
    if (error.response.status === 401) {
      // 处理未授权错误
      console.error('用户未登录或 token 已过期');
    }
    return Promise.reject(error);
  }
);

export default request;
  1. 可以为所有的接口统一一个 baseURL, 方便做反向代理

  2. 可以为所有的请求配置超时时间

  3. 设置统一请求头

  4. 支持请求拦截和相应拦截

  5. 自动将请求体序列化

    • JSON (application/json): 如果你发送的数据是一个 JavaScript 对象,并且没有特别指定其他形式,Axios 默认会将其序列化为 JSON 格式,并设置 Content-Typeapplication/json

    • Multipart / FormData (multipart/form-data): 当你需要上传文件或者同时发送文件和文本信息时,通常会使用这种格式。你可以创建一个 FormData 对象,然后将你的数据添加到这个对象中。Axios 会识别出这是一个 FormData 实例,并相应地设置 Content-Typemultipart/form-data

    • URL encoded form (application/x-www-form-urlencoded): 这种格式通常用于表单提交,数据被编码为键值对的形式。如果你要手动实现这一点,可以使用 URLSearchParams 接口或其他方法来序列化你的数据。不过,Axios 也允许你通过特定配置(如 qs 库)轻松地转换你的 JavaScript 对象为这种格式。

  6. 请求接收到的格式为 json时,axios 将其会自动转化为 javascript 对象

注意: axios是一个 js 库,跟使用的 vue 还是 reactvite 还是 webpack没有关系;在任何一个技术栈的 web 项目中都可以使用

6.4 baseURLvite 反向代理

学习到此,我们终于准备好了所有配置反向代理的前置知识,现在将其融汇贯通,来配置反向代理

//...
 proxy: {
    // 当请求以 '/api' 开头时,将其转发到目标地址,一般配置在 baseURL
    '/api': {
      target: 'http://localhost:3000', // 目标服务器地址
      changeOrigin: true, // 是否改变请求源信息
      rewrite: path => path.replace(/^\/api/, ''), // 路径重写规则,将前缀 /api 替换为空字符串
      secure: false, // 如果是https接口,需要配置该参数为false
    }
  },
//...

其中的/api, 需要和我们刚刚创建的axios实例的 baseURL 对应上,这个配置的意思是:

  1. 将开头为/api的请求
  2. 代理到 target字段的值 (这个值,一般是对应的后端地址)
  3. changeOrigin:true 的意思是,改变 origin(包括协议、主机名和端口号)
  4. rewrite: path => path.replace(/^\/api/, '')转发后的地址,重写请求 url,将/api去掉

注意: 以上配置按需写,尤其是 rewrite, 需要先想好或者看项目,请求是什么样子,以及完整的请求 url 是什么样子,再决定是否要 rewrite;

注意: 反向代理的配置,vitewebpack 的思路基本一致,具体可参考webpack.devServer.proxy 配置

注意: 所有 vite.config.t(j)s关于反向代理的配置,全部都是开发阶段的配置,部署上线之后是不生效的 !! 线上可以采用 nginx, 参考本地开发阶段的配置进行反向代理

6.5 如何找到项目中的接口封装以及如何使用封装好的 axios实例

说是封装好的 axios 的对象其实并不准确,按照官网的说法,应该是 axios 实例(通过axios.create([config])创建)

如何找到项目中放接口的目录
  1. scr/api(request)/server
  2. 全局搜索 getpostputdelete
如何使用刚刚封装好的axios实例

一般来说,我们会把所有的请求放在一个公共目录下,并分模块将请求分开,以便于复用

import request from '@/utils/request';

const getUserList = () => request.get('/v1/users');

const postUser = data => request.post('/v1/users', data);

// typescript
const postUserDetail = (params: { id: string }) =>
  request.get('/v1/users', {
    params,
  });
// ...
export {
  getUserList,
  postUser,
  postUserDetail, // ...
};

然后,我们在实际的业务中通过 import语句,在业务代码中导入对应封装好的请求即可使用

import {getUserList, postUser, postUserDetail} from '@/server/user'
import { IUser } from '@/model/user'

const state = reactive<{
  userList: IUser[]
}> ({
  userList: []
})

const getList = async () => {
  try {
    const res = await getUserList ();
    const state.userList = [...res.data]
  }catch (err) {
    console.error (err)
  }
}