1、创建项目

使用vue-ts模板创建项目

npm create vite my-vue-app --template vue-ts

 项目目录截图

2、安装和配置vue-router

2.1、安装vue-router

npm install vue-router@4 -S

2.2、配置vue-router

2.2.1、在src创建router文件夹并且在router文件夹下创建index.ts文件

import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";

const routes: Array<RouteRecordRaw> = [
    {
        path: "/",
        name: "home",
        /** 在src/views 文件下创建home文件 */
        component: () => import("../views/home/index.vue"),
    },
    {
        path: "/about",
        name: "about",
        /** 在src/views 文件下创建about文件 */
        component: () => import("../views/about/index.vue"),
    },
];

const router = createRouter({
    history: createWebHistory(),
    routes,
});

export default router;

2.2.2、在main.ts文件中添加router引用

import { createApp } from 'vue'

/** --- 新增代码块 start --- */
import router from './router';
/** --- 新增代码块 end --- */

import './style.css'
import App from './App.vue'

/** --- 修改代码块 end --- */
const app = createApp(App);
app.use(router);


app.mount('#app')
/** --- 修改代码块 start --- */

2.2.3、修改App.vue,删除之前代码,改成如下代码块

<template>
    <div>
        <router-view></router-view>
    </div>
</template>

<style lang="less" scoped>

</style>

3.1、安装pinia

npm install pinia -S

3.2、配置vuex

3.2.1、在src下创建store文件夹并在store文件夹下创建index.ts文件、modules文件夹

import { createPinia } from "pinia";
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";

// pinia persist
const pinia = createPinia();
pinia.use(piniaPluginPersistedstate);

export default pinia;

3.2.2、在modules文件夹下创建users.ts(你可以创建自己需要的文件)

import { defineStore } from "pinia";


interface UserVO {
  id: number;
  avatar: string;
  nickname: string;
}
interface UserInfoVO {
  user: UserVO;
}

export const useUserStore = defineStore("admin-user", {
  state: (): UserInfoVO => ({
    user: {
      id: 0,
      avatar: "",
      nickname: ""
    }
  }),
  getters: {
    getUser(): UserVO {
      return this.user;
    }
  },
  actions: {
    // Set setUserInfo
    setUserInfo(userInfo: UserVO) {
      this.user = userInfo;
    }
  }
});

3.2.3、在main.ts文件中添加store引用

import { createApp } from 'vue'
/** --- 新增代码 start --- */
import store from './store'
/** --- 新增代码 end --- */
import router from './router'

import './style.css'
import App from './App.vue'

const app = createApp(App)
/** --- 新增代码 start --- */
app.use(store)
/** --- 新增代码 end --- */
app.use(router)

app.mount('#app')

4、安装和配置axios

4.1、安装axios

npm install axios -S

4.2、配置axios

4.2.1、配置封装axios,这边把封装的axios放在了src/utils/request 目录下,分别创下一下文件

  •   errorCode.ts,状态码对应提示

export default {
  '401': '认证失败,无法访问系统资源',
  '403': '当前操作没有权限',
  '404': '访问资源不存在',
  'default': '系统未知错误,请反馈给管理员'
}
  • axios.ts  axios封装
import axios from 'axios'
import { ElMessage, ElMessageBox, ElNotification } from "element-plus";
import errorCode from '@/utils/request/errorCode'
// import { getToken, removeToken } from '@/utils/auth'

// 是否显示重新登录
export const isRelogin = { show: false }

// axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
  // axios中请求配置有baseURL选项,表示请求URL公共部分
  baseURL: import.meta.env.VITE_BASE_URL,
  // 超时
  timeout: 10000
})

// request拦截器
service.interceptors.request.use(config => {
  // 是否需要设置 token
  // const isToken = (config.headers || {}).isToken === false
  // if (getToken() && !isToken && config && config?.headers) {
    // config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定 
   // 义token 请根据实际情况自行修改
  //}
  return config
}, error => {
  console.log(error)
  Promise.reject(error)
})

// 响应拦截器
service.interceptors.response.use(res => {
  // 未设置状态码则默认成功状态
  const code = res.data.code
  // 获取错误信息
  const msg: string = errorCode[code as keyof typeof errorCode] || res.data.msg || errorCode['default']
  // 二进制数据则直接返回
  if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
    return res.data
  }
  if (code === 401) {
    if (!isRelogin.show) {
      isRelogin.show = true
      ElMessageBox.confirm("登录超时,请重新登录!", "系统提示", {
        showCancelButton: false,
        closeOnClickModal: false,
        showClose: false,
        confirmButtonText: "重新登录",
        type: "warning"
      }).then(() => {
        // removeToken()
        isRelogin.show = false;
        // 干掉token后再走一次路由让它过router.beforeEach的校验
        // window.location.href = window.location.href;
        location.href = '/login'
      });
    }
    return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
  } else if (code === 500) {
    ElMessage.error(msg)
    return Promise.reject(new Error(msg))
  } else if (code !== 200) {
    ElNotification.error({
      title: msg
    })
    return Promise.reject('error')
  } else {
    return res.data
  }
},
  error => {
    let msg = error.message
    if (msg == 'Network Error') {
      msg = '后端接口连接异常'
    } else if (msg.includes('timeout')) {
      msg = '系统接口请求超时'
    } else if (msg.includes('Request failed with status code')) {
      msg = '系统接口' + msg.substr(msg.length - 3) + '异常'
    }
    ElMessage.error(msg)
    return Promise.reject(msg)
  }
)

export default service
  • index.ts  封装对外请求暴露接口
import axios from './axios'

/**
 * 将Object数据转换成字符串拼接数据(格式为?a=a&b=b)
 * @param {*} params
 * @returns
 */
const getParamsStr = (params: any) => {
  let paramstr = ''
  const param = params || {}
  if (param) {
    let index = 0
    for (const key in param) {
      if (index > 0) {
        paramstr += '&'
      }
      paramstr += key + '=' + encodeURI(param[key])
      index++
    }
  }
  if (paramstr.length > 0) {
    // paramstr = '?' + paramstr;
  }
  return paramstr
}

export default {
  /**
   * get方法,对应get请求
   * @param {String} url [请求的url地址]
   * @param {Object} params [请求时携带的参数]
   */
  get: (url: string, params?: any, headers?: any) => {
    headers = headers || { isToken: true }
    return new Promise((resolve, reject) => {
      axios
        .get(url, {
          params: params || '',
          headers
        })
        .then((res: any) => {
          resolve(res)
        })
        .catch((err: string) => {
          reject(err)
        })
    })
  },
  /**
   * post方法,对应post请求
   * @param {String} url [请求的url地址]
   * @param {Object} params [请求时携带的参数]
   */
  post: (url: string, params?: any, headers?: any) => {
    headers = headers || { isToken: true }
    return new Promise((resolve, reject) => {
      axios
        .post(url, params, {
          headers: {
            ...headers,
            'Content-Type': 'application/json;charset=UTF-8'
          }
        })
        .then((res: any) => {
          resolve(res)
        })
        .catch((err: string) => {
          reject(err)
        })
    })
  },

  /**
   * formPost方法,对应post请求
   * @param {String} url [请求的url地址]
   * @param {Object} params [请求时携带的参数]
   */
  formPost: (url: string, params: any, headers?: any) => {
    headers = headers || { isToken: true }
    return new Promise((resolve, reject) => {
      axios
        .post(url, getParamsStr(params), {
          headers: {
            ...headers,
            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
          }
        })
        .then((res: any) => {
          resolve(res)
        })
        .catch((err: string) => {
          reject(err)
        })
    })
  },

  /**
   * formDataPost方法,对应post请求
   * @param {String} url [请求的url地址]
   * @param {Object} params [请求时携带的参数]
   */
  formDataPost: (url: string, params?: any, headers?: any) => {
    headers = headers || { isToken: true }
    return new Promise((resolve, reject) => {
      axios
        .post(url, params, {
          headers: {
            headers,
            'Content-Type': 'multipart/form-data'
          }
        })
        .then(res => {
          resolve(res.data)
        })
        .catch(err => {
          reject(err.data)
        })
    })
  },
  /**
   * delete方法,对应post请求
   * @param {String} url [请求的url地址]
   * @param {Object} params [请求时携带的参数]
   */
  delete: (url: string, params?: any, headers?: any) => {
    headers = headers || { isToken: true }
    return new Promise((resolve, reject) => {
      axios
        .delete(url, {
          params: params || '',
          headers
        })
        .then((res: any) => {
          resolve(res)
        })
        .catch((err: string) => {
          reject(err)
        })
    })
  },

  /**
   * put请求
   * @param url 接口路由
   * @param data 接口参数
   * @param auth 是否需要带登录信息
   * @returns {AxiosPromise<any>}
   */
  put: (url: string, params?: any, headers?: any) => {
    headers = headers || { isToken: true }
    return new Promise((resolve, reject) => {
      axios
        .put(url, params, {
          headers: {
            ...headers,
            'Content-Type': 'application/json;charset=UTF-8'
          }
        })
        .then((res: any) => {
          resolve(res)
        })
        .catch((err: string) => {
          reject(err)
        })
    })
  },
  download: (url: string, params: any, filename: string) => {
    return new Promise((resolve, reject) => {
      console.log(url, filename)
      resolve(1)
      reject(2)
    })
  }
}

4.3、创建api接口

4.3.1、创建api目录,(建议:分模块使用接口,这边案例使用的是login.ts)

import request from '@/utils/request'
import { LoginParams } from '@/constants/params/login' // 在公共目录下创建api参数对应的数据类型


// 登录方法
export function login(params: LoginParams) {
  return request.post('/login', params, { isToken: false })
}

constants/params 目录下的 login.ts

export interface LoginParams {
  username: string,
  password: string,
  rememberMe: boolean,
  code: string,
  uuid: string
}

5、安装和配置 element-plus

5.1、安装 element-plus

 npm install element-plus -S

5.2、配置 element-plus

参考:快速开始 | Element Plus

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐