前些日子,做了一個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)歷,希望對你有用!