vue3.0+ts+axios封裝+跨域

前些日子,做了一個vue的H5項目,前后端分離,采用的是vue3.0+ts+axios,過程中采了些坑,分享出來,希望能對遇到相似坑的碼友有所幫助!

想了想還是從最基礎(chǔ)的開始講,照顧一些像我這樣的小白,老鳥自行跳過;


一、環(huán)境安裝

1.modeJs安裝:

Node.js 安裝包及源碼下載地址為:https://nodejs.org/en/download/。下載完后傻瓜式安裝就行;

2.安裝vue3.0

打開Powershell或cmd命令工具執(zhí)行?npm install -g @vue/cli


二、項目搭建

1. 選擇自己的項目目錄,執(zhí)行 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協(xié)議 ?

? ? ? ? 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)

? ? ? ? ? ? }

? ? ? ? );

? ? ? ? // 響應(yīng)攔截器

? ? ? ? this.instance.interceptors.response.use(

? ? ? ? ? ? (response) => {

? ? ? ? ? ? ? ? const result = response.data

? ? ? ? ? ? ? ? if (!response.status.toString().startsWith("2") || result.code === -1) {

? ? ? ? ? ? ? ? ? ? // 如果狀態(tài)碼不是2開頭或者接口code返回-1 則是返回錯誤信息

? ? ? ? ? ? ? ? ? ? console.error("系統(tǒng)錯誤,請檢查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("系統(tǒng)錯誤,請檢查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.我將發(fā)送請求封裝在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 ,做跨域后現(xiàn)實的請求地址是 http://192.168.1.9:8080/api/register,雖然看上去還是本地地址,但實際是請求了http://www.baidu.com/register;


四、使用方式,這里我使用了async+await的方式,本人不喜歡then的風格,舉個栗子,model.ts(模型層,從api中請求數(shù)據(jù),返回給入口文件index.ts)、index.ts(模塊入口,梳理接口數(shù)據(jù)并按需作邏輯處理):

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>

以上就是我的經(jīng)歷,希望對你有用!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容