前些日子,做了一个vue的H5项目,前后端分离,采用的是vue3.0+ts+axios,过程中采了些坑,分享出来,希望能对遇到相似坑的码友有所帮助!
想了想还是从最基础的开始讲,照顾一些像我这样的小白,老鸟自行跳过;
一、环境安装
1.modeJs安装:
Node.js 安装包及源码下载地址为:https://nodejs.org/en/download/。下载完后傻瓜式安装就行;
2.安装vue3.0
打开Powershell或cmd命令工具执行 npm install -g @vue/cli
二、项目搭建
1. 选择自己的项目目录,执行 vue create 项目名
2. 下面是选择:
? Please pick a preset: Manually select features
? Check the features needed for your project: Choose Vue version, Babel, TS, Router, Vuex, CSS Pre-processors, Linter
? Choose a version of Vue.js that you want to start the project with 3.x
? Use class-style component syntax? No
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Sass/SCSS (with dart-sass)
? Pick a linter / formatter config: Basic
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No
3. 可以看见,是没有vue.config.js的,我们需要手动在项目根目录下添加这个文件(PS:一定不要将扩展名写成.ts,这是血一样的教训,扩展名只能是.js)
下面是我的配置:
module.exports = {
devServer: {
open: false, // 是否自动弹出浏览器页面
host: '0.0.0.0',
port: '8080',
https: false, // 是否使用https协议
hotOnly: true, // 是否开启热更新
disableHostCheck: true,
proxy: {
'/api': { //这个名字与 interceptors.ts 中的 baseURL 一定要一致,切记!
target: '要请求的api基地址',
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}
三、axios封装
1.先封装拦截器interceptors.ts
上代码:
import axios, { AxiosInstance } from "axios"
export class Interceptors {
instance: AxiosInstance
constructor() {
this.instance = axios.create({
baseURL: '/api', //vue.config.js中的命名,上述说到了
timeout: 10000,
});
}
// 初始化拦截器
init() {
// 请求接口拦截器
this.instance.interceptors.request.use(
(config) => {
// 判断一下是否有cookie 如果有的话则把cookie放入请求头中
config.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8'
return config
},
(err) => {
console.error(err)
}
);
// 响应拦截器
this.instance.interceptors.response.use(
(response) => {
const result = response.data
if (!response.status.toString().startsWith("2") || result.code === -1) {
// 如果状态码不是2开头或者接口code返回-1 则是返回错误信息
console.error("系统错误,请检查API是否正常!")
return
}
if (result.code !== 200) {
if (result.code === -3) {
console.error("登录过期")
//清除本地的token
} else {
if (result.msg) {
console.error(result.msg)
}
}
return Promise.resolve(result)
} else {
// 返回成功则把token存储一下
return result
}
},
(error) => {
if (error.message === "Request failed with status code 500") {
console.error("系统错误,请检查API是否正常!")
return
}
let code = -110
if (error && error.response && error.response.status) {
code = error.response.status
// 登录过期
if (code === 401 || code === -3) {
//清除本地token
}
} else {
console.error(error.message)
}
const err = { errCode: -110, errMsg: error.message || "Error" }
return Promise.resolve(err)
}
);
}
// 返回一下
getInterceptors() {
return this.instance
}
}
2.我将发送请求封装在http.ts:
import { AxiosPromise, AxiosResponse } from "axios"
import { Interceptors } from "./interceptors"
// 请求配置
export class HttpServer {
axios: any
// 获取axios实例
constructor() {
this.axios = new Interceptors().getInterceptors()
}
// 简单封装一下方法
request(config: any): AxiosPromise {
return new Promise((resolve, reject) => {
this.axios(config).then((result: AxiosResponse) => {
resolve(result)
}).catch((err: any) => {
reject(err)
})
});
}
}
const Http = HttpServer
export default Http
PS:加入我们要请求:http://www.baidu.com/register ,做跨域后现实的请求地址是 http://192.168.1.9:8080/api/register,虽然看上去还是本地地址,但实际是请求了http://www.baidu.com/register;
四、使用方式,这里我使用了async+await的方式,本人不喜欢then的风格,举个栗子,model.ts(模型层,从api中请求数据,返回给入口文件index.ts)、index.ts(模块入口,梳理接口数据并按需作逻辑处理):
1.model.ts:
import Http from '@/http'
import { Method } from 'axios';
export default class TestModel extends Http {
registerModel(data: any): any{
const url = '除去api基地址外的路径,如(http://www.baidu.com/register 只需写 '/register')'
const param = {
url,
data,
method: <Method>'POST'
}
return this.request(param)
}
}
2.index.ts:
import UserModel from './model'
export default class UserServer extends UserModel {
register(data: any): any{
return new Promise(async resolve => {
const result = await this.registerModel(data)
if (result) {
//逻辑处理后
resolve({ ...result })
}
})
}
}
3.test.vue:
<template>
<div>
<div class="clum">
<button @click="config">点击测试</button>
</div>
</div>
</template>
<script lang="ts">
/* 导入模块 */
import TestServer from '@/api/index'
/* 实例化模块 */
const server = new TestServer()
export default {
name: 'test',
data(){
return {
}
},
methods: {
async register(){
const result = await server.config()
console.log(result)
}
}
};
</script>
以上就是我的经历,希望对你有用!