vue3+ts项目搭建和封装(下篇)

简介: vue3+ts项目搭建和封装(下篇)

配置request.ts



/**
 * axios 二次封装 
 * @auther 何小生。
 * @time 2021/08/05 05:24
*/
import axios from 'axios'   // 引入axios
import { config } from '../config'  // 引入config
import { ElMessage } from 'element-plus'  // 引入element-plus
import router from '../router'  // 由于有些token认证失效等需要用到,所以引入router
import { storage } from './storage'  // 引入storage,用于获取缓存
// 定义初始化状态码
const TOKEN_INVALID = 'Token认证失败, 请重新登录'
const NETWORK_ERROR = '网络请求异常, 请稍后重试'
// 创建axios实例对象, 添加全局配置
const service = axios.create({
    // 初始配置请求头  当环境为mock的时候,请求mockapi,否则请求正式的api
    baseURL: config.mock ? config.mockApi : config.baseApi,
    // 接口持续时间为8秒,否则超时
    timeout: 8000
})
// 请求拦截
service.interceptors.request.use((req) => {
    // TO-DO
    // 获取请求头
    const headers = req.headers
    // 获取token 由于是typescript,所以要做排斥赋值
    const { token = "" } = storage.get('userInfo') || {}
    // 跟后端定义的某个请求头的值用于解析token身份令牌
    if(!headers.Authorization) headers.Authorization = 'xiaohe ' + token
    // 返回请求头
    return req
})
// 响应拦截
service.interceptors.response.use((res) => {
    // 获取后端返回的code,data和提示语
    const { code, data, msg } = res.data
    if(code == 200) return data
    else if(code === 50001) {   // token认证失败
        ElMessage.error(TOKEN_INVALID)   // 给予5001的状态码
        // 并且给予用户 一定的反应时间后,跳转登录页
        setTimeout(() => {
            router.push('/login')
        }, 15000)
        return Promise.reject(TOKEN_INVALID)  // 抛出异常
    } else {
        // 丢出服务器异常
        ElMessage.error(msg || NETWORK_ERROR)
        return Promise.reject(msg || NETWORK_ERROR)
    }
})
/**
 * @param {*} options   请求配置
*/
function request(options: any) {
    options.method = options.method || 'get'
    if(options.method.toLowerCase() === 'get') options.params = options.data
    if(typeof options.mock != 'undefined') config.mock = options.mock
    if(config.env === 'prod') service.defaults.baseURL = config.baseApi
    else service.defaults.baseURL = config.mock ? config.mockApi : config.baseApi
    return service(options)
}
// 轮询接口类型,然后根据对应的类型,给予请求方式
['get', 'post', 'put', 'delete', 'patch'].forEach(item => {
    request[item] = (url: string, data: any, options: string[]) => {
        return request({ url, data, method: item, ...options })
    }
})
// 丢出request
export default request
复制代码


封装storage.ts



此处用到了storage和sessionStorage两种方法做缓存封装


/**
 * 封装操作localstorage本地存储的方法
 * @auther 何小玍。
 * @date 2021/06/28
 */
export const storage = {
    //存储
    set(key: string, value: any) {
        window.localStorage.setItem(key, JSON.stringify(value))
    },
    //取出数据
    get<T>(key: string) {
        const value = window.localStorage.getItem(key)
        if (value && value != "undefined" && value != "null") return <T>JSON.parse(value)
        else return "{}"
    },
    // 删除数据
    remove(key: string) {
        window.localStorage.removeItem(key)
    }
};
/**
 * 封装操作sessionStorage本地存储的方法
 */
export const sessionStorage = {
    //存储
    set(key: string, value: any) {
        window.sessionStorage.setItem(key, JSON.stringify(value))
    },
    //取出数据
    get<T>(key: string) {
        const value = window.sessionStorage.getItem(key);
        if (value && value != "undefined" && value != "null") return JSON.parse(value)
        return null
    },
    // 删除数据
    remove(key: string) {
        window.sessionStorage.removeItem(key)
    }
}
复制代码


配置config.ts



在src目录下创建config文件夹,然后创建index.ts, 用于配置请求的基本配置参数和区分生产环境和开发环境


export interface IConfig {
    env: string // 开发环境
    mock?: boolean // mock数据
    title: string // 项目title
    baseApi?: string // api请求地址
    mockApi?: string // mock地址
}
const dev: IConfig = {
    env: "development",
    mock: false,
    title: "开发",
    baseApi: "/api", // 本地api请求地址,注意:如果你使用了代理,请设置成'/'
    mockApi: "https://www.fastmock.site/mock/4f8c864d98d32e623e4a452a904ca70b/api"
}
const prod: IConfig = {
    env: "production",
    mock: false,
    title: "生产",
    baseApi: "https://www.baidu.com/api", // 正式api请求地址
    mockApi: 'xxx'
}
export const config: IConfig = import.meta.env.MODE == 'development' ? dev : prod
复制代码


配置api封装



在src目录下,创建api文件夹,然后生成user.ts文件,存放登录注册忘记密码等接口


import request from '../utils/request'
interface userState {
    username: string
    password: string
}
export default {
    /**
     * 登录接口
     * @param { string } username       用户名称
     * @param { string } password       用户密码
     */
    login( data: userState ) {
        return request({
            url: '/users/login',
            method: 'post',
            data
        })
    }
}
复制代码


配置router和路由守卫



在src文件夹下创建index.ts、router.config.ts

  • 路由守卫的配置


import { createRouter, createWebHistory } from "vue-router"
import { constantRouterMap } from "./router.config"
import { useDocumentTitle } from "@/hooks/useDocumentTitle"
import store from "@/store"
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  // 在按下 后退/前进 按钮时,就会像浏览器的原生表现那样
  scrollBehavior(to, from, savedPosition) {
    if (savedPosition) return savedPosition
    else return { top: 0 }
  },
  routes: constantRouterMap
})
// 路由开始进入
router.beforeEach((to: any, from: any, next) => {
  useDocumentTitle(to.meta.title)
  next()
  return false
})
router.afterEach((to, from, next) => {
  // 保存url
})
export default router
复制代码


  • 路由配置


import { RouteRecordRaw } from "./vue-router"
import Layout from '@/layout/index.vue'
export const constantRouterMap: Array<RouteRecordRaw> = [  
  { path: '/login', name: 'login', component: () => import('@/views/login/login.vue'), meta: { title: '登录' }, hidden: true },
  { path: '/', name: '/', component: Layout, redirect: '/index', meta: { title: '博客', icon: 'el-icon-help' }, children: [
    { path: '/index', name: 'index', component: () => import('@/views/index/index.vue'), meta: { title: '博客', icon: 'el-icon-link' } }
  ] },
  { path: '/404', name: 'page404', component: () => import('@/views/404.vue'), meta: { title: '404' }, hidden: true },
  { path: '/:catchAll(.*)', redirect: '/404', hidden: true }
]
复制代码


main.js配置



最后在main.js里面配置


import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import svgIcon from './icons/index.vue'
import { storage, sessionStorage } from './utils/storage'
import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'
// 引入全局样式
import "./styles/base.css"
import "./styles/reset.css"
const app = createApp(App)
app.config.globalProperties.storage = storage                   // 全局挂载 缓存方法
app.config.globalProperties.sessionStorage = sessionStorage     // 全局挂载 缓存方法
app
.use(router)
.use(store)
.use(ElementPlus)
.component('svg-icon', svgIcon)
.mount('#app')


相关文章
|
1天前
|
缓存 JavaScript UED
Vue3中v-model在处理自定义组件双向数据绑定时有哪些注意事项?
在使用`v-model`处理自定义组件双向数据绑定时,要仔细考虑各种因素,确保数据的准确传递和更新,同时提供良好的用户体验和代码可维护性。通过合理的设计和注意事项的遵循,能够更好地发挥`v-model`的优势,实现高效的双向数据绑定效果。
102 64
|
1天前
|
JavaScript 前端开发 API
Vue 3 中 v-model 与 Vue 2 中 v-model 的区别是什么?
总的来说,Vue 3 中的 `v-model` 在灵活性、与组合式 API 的结合、对自定义组件的支持等方面都有了明显的提升和改进,使其更适应现代前端开发的需求和趋势。但需要注意的是,在迁移过程中可能需要对一些代码进行调整和适配。
|
23天前
|
JavaScript 数据管理 Java
在 Vue 3 中使用 Proxy 实现数据双向绑定的性能如何?
【10月更文挑战第23天】Vue 3中使用Proxy实现数据双向绑定在多个方面都带来了性能的提升,从更高效的响应式追踪、更好的初始化性能、对数组操作的优化到更优的内存管理等,使得Vue 3在处理复杂的应用场景和大量数据时能够更加高效和稳定地运行。
39 1
|
8天前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
vue学习第四章
|
8天前
|
JavaScript 前端开发
vue学习第九章(v-model)
欢迎来到我的博客,我是瑞雨溪,一名热爱JavaScript与Vue的大一学生,自学前端2年半,正向全栈进发。此篇介绍v-model在不同表单元素中的应用及修饰符的使用,希望能对你有所帮助。关注我,持续更新中!🎉🎉🎉
vue学习第九章(v-model)
|
7天前
|
JavaScript 前端开发 开发者
vue学习第十章(组件开发)
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文深入讲解Vue组件的基本使用、全局与局部组件、父子组件通信及数据传递等内容,适合前端开发者学习参考。持续更新中,期待您的关注!🎉🎉🎉
vue学习第十章(组件开发)
|
13天前
|
JavaScript 前端开发
如何在 Vue 项目中配置 Tree Shaking?
通过以上针对 Webpack 或 Rollup 的配置方法,就可以在 Vue 项目中有效地启用 Tree Shaking,从而优化项目的打包体积,提高项目的性能和加载速度。在实际配置过程中,需要根据项目的具体情况和需求,对配置进行适当的调整和优化。
|
13天前
|
存储 缓存 JavaScript
在 Vue 中使用 computed 和 watch 时,性能问题探讨
本文探讨了在 Vue.js 中使用 computed 计算属性和 watch 监听器时可能遇到的性能问题,并提供了优化建议,帮助开发者提高应用性能。
|
13天前
|
存储 缓存 JavaScript
如何在大型 Vue 应用中有效地管理计算属性和侦听器
在大型 Vue 应用中,合理管理计算属性和侦听器是优化性能和维护性的关键。本文介绍了如何通过模块化、状态管理和避免冗余计算等方法,有效提升应用的响应性和可维护性。
|
13天前
|
存储 缓存 JavaScript
Vue 中 computed 和 watch 的差异
Vue 中的 `computed` 和 `watch` 都用于处理数据变化,但使用场景不同。`computed` 用于计算属性,依赖于其他数据自动更新;`watch` 用于监听数据变化,执行异步或复杂操作。
下一篇
无影云桌面