快速掌握Vue3:速成Vue3前端开发看这篇就够啦

这篇具有很好参考价值的文章主要介绍了快速掌握Vue3:速成Vue3前端开发看这篇就够啦。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、Vue基本概念

1.1-Vue3的优点

  • Vue3支持Vue2额大多数特性。
  • 更好的支持TypeScript。
  • 打包大小减少41%。
  • 初次渲染快55%,更新渲染快133%。
  • 内存减少54%。
  • 使用proxy代替defineProperty实现数据响应式。
  • 重写虚拟DOM的实现和Tree-Shaking。

二、API

2.1-setup

我们可以跟以前定义data和methods,但是vue3中我们更推荐使用setup函数。

  • setup是一个函数。只在初始化时执行一次。以后大部分代码都是在setup中写。
  • 返回一个对象,对象中的属性或方法,模板中可以直接使用。
  • setup返回的数据会和data和methods进行合并,setup优先级更高。
  • setup函数中没有this。 以后开发都不使用this了
  • setup不要写async函数。

因为async函数必须返回一个json对象供模板使用,如果setup是一个async函数,返回的将是一个promise对象。
如果setup是一个async函数,那该组件就成了一个异步函数,需要配合Suspense组件才能使用。


2.2-ref

让数据变成响应式。

(1)先引用ref
import {ref} from 'vue';

(2)将数据变成响应式的。
let data1=ref(12);

(3)操作数据
data1.value = 123;

2.3-reactive

作用:定义对象格式的响应式数据
如果用ref定义对象/数组,内部会自动将对象/数组转换为reactive代理器对象。

  • const proxy=reactive(obj):接收一个普通对象然后返回该普通对象的响应式代理器对象。
  • js中修改告诉不需要.value。
  • 一般用来定义一个引用类型的响应数据。

2.4-toRefs

将响应式对象中所有属性包装为ref对象,并返回包含这些ref对象的普通对象。
应用:对trsctive定义的对象进行toRefs包装,包装之后的对象中每个属性都是响应式的。


2.5-响应式原理

通过proxy(代理):拦截对对象本身的操作,包括属性的读写、删除等操作。
通过Reflect(反射):动态对被代理对象的响应式属性进行特定的操作。


2.6-watch和watchEffect

watch - 指定监听数据:

  • 监听指定的一个或多个响应式数据,一旦发生变化,就会自动执行监视回调。
    • 如果是监听reactive对象中的属性,必须通过函数来指定。
    • 监听多个数据,使用数组来指定。
  • 默认初始时不指定回调,但是通弄过配置immediate为true,来指定初始时立即执行第一次。
  • 通过配置deep为true,来指定深度监视。

watchEffect - 不指定监听数据:

  • 不用直接指定啦监视的数据,回调函数中使用的哪些响应式数据就监听哪些响应式数据。
  • 默认初始就会执行一次。

2.7-生命周期

vue2中的生命周期钩子函数依旧可以使用,不过建议使用vue3的钩子函数

快速掌握Vue3:速成Vue3前端开发看这篇就够啦


2.8-ref获取元素

vue2中是用thisref.xxx来获取元素或组件,但是vue3中没有this的概念。
vue3通过ref创建响应式数据的api来获取元素。

1.使用ref创建响应式数据,假设叫x
2.模板中绑定ref属性,值为上面的x
注意不能使用v-bind动态绑定。
这是x就是一个dom元素或组件了。


2.9-自定义hook函数

hook函数翻译成中文就是钩子函数(注意并不是生命周期的钩子函数)
比如ref,reactive,computed,watch,onBeforeMount等都是hook函数,只不过他们都是vue内部hook函数。

1.创建一个函数,函数名称必须以"use"开头
2.函数必须return一些数据。


2.10-shallowReactive与shallowRef

他们都表示浅响应式。

  • shallowReactive:只处理了对象第一层属性的响应式(值响应第一层)
  • shallowRef:只有重新复制时才是响应式(不响应内部数据,只响应整体。)

2.11-readonly与shallowReadonly

  • 他们表示只读代理对象
  • readonly
    • 深度只读
    • 设置readonly后,修改响应式数据会报错。
  • shalloReadonly
    • 浅只读
    • 设置shalloReadonly后,修改响应式数据的第一层数据会报错。
  • 应用场景:
    • 在某些特定情况下,我们可能不希望对数据进行更新的操作,那就可以包装成一个只读代理对象,而不能修改或删除。

2.12-toRaw与markRaw

  • toRaw
    • 返回reactive或readonly对象的原始数据
    • 这是一个还原方法,可用于临时读取,得到的数据不具有响应式。
  • markRow:
    • 标记一个对象,使其不具有响应式
    • 应用场景:
      • 有些只不应被设置为响应式的,例如复杂的第三方实例或Vue组件对象。
      • 当渲染具有不可变数据源的大列表时,跳过代理转换可以提高性能。

2.13-toRef

  • 为响应式对象上的某个属性创建一个ref引用,更新是应用对象会同步更新。
  • 与ref的区别:ref是拷贝了一份新的数据指单独操作,更新时相互不影响。

2.14-customRef

  • 用于自定义一个ref,可以显示的控制依赖追踪和触发相应。
  • 接受一个工厂函数,两个参数分别用于追踪的track与用于触发相应的trigger,并方法一个带有get和set属性的对象。
  • 需求:使用customRef实现防抖函数

2.15-provide与inject

  • provide和inject提供依赖注入,功能类似2.0的provide/inject
  • 实现跨层级组件(祖孙)间通信。

2.16-响应式数据的判断

  • isRef:检查一个值是否为一个ref对象。
  • isReactive:检查一个对象是否否是由reactive对象的响应式代理。
  • isReadonly:检查一个对象是否由readonly创建的只读代理。
  • isProxy:检查一个对象是否是由reactive或者readonly方法创建的代理。

2.17-Fragment(片段)

  • 在vue2中:组件中必须有一个跟标签
  • 在vue3中:组价可以没有跟标签,内部会将多个标签包含在一个Fragment虚拟标签中。
    • 好处:减少标签层级,减小内存占用

2.18-Teleport(瞬移)

  • Teleport提供了一种干净的方法,让组件的html在父组件界面外的特定标签(很可能是body)下插入显示。

2.19-Suspense(不确定的)

Supense组件是配合一部组件使用的,它可以让一部组件返回数据前渲染一些后背内容。
那我们首先要学会一个异步组件。

  • 在setup函数总返回一个promise,就是一个异步组件。
  • setup函数携程async函数,也是一个异步组件。

2.20-其他新的API

  • 全新的全局API:
    • createApp()
    • defineProperty()
    • defineComponent()
    • nextTick()
  • 将原来的全局API转移到应用对象:
    • app.component()
    • app.config()
    • app.directive()
    • app.mount()
    • app.umount()
    • app.use()

2.21-useSlots和useAttrs

useSlots 和 useAttrs 是真实的运行时函数,它会返回与 setupContext.slots 和 setupContext.attrs 等价的值,同样也能在普通的组合式 API 中使用。
使用场景:父组件使用子组件的插槽

1.父组件

<template>
  <h1>这是父组件</h1>

  <p>插槽上面1</p>
  <slots-attrs msg="我是props的msg" heihei="我是attr">
    <template #header >
      <div style="width:100%;height:100px;border:1px solid green;">我是父组件插槽--插入的内容。。。</div>
    </template>
  </slots-attrs>
  <p>插槽下面2</p>

</template>

<script lang="ts" setup>
import SlotsAttrs from '@/components/04/SlotsAttrs.vue'

</script>

2.子组件

<template>
  <Child ref="child"/>

  {{msg}}
</template>


<script lang="ts" setup>
import { ref,onMounted } from 'vue';
import Child from '@/components/03/Child.vue'


const child = ref(null);
const msg=ref('')




onMounted(()=>{
  console.log("进来了")
  console.log(child.value.msg)
  msg.value = child.value.msg;
})

</script>

三、路由

(1)userRout:获得当前路由对象。
(2)useRouter:获得路由实例,可以进行路由跳转。

import {useRoute,useRouter} from "vue-router"

四、Vue3+TS实战知识点

1.1-引入ElementPlus

(1)输入命令安装(全局引入)。

npm install element-plus --save

(2)【main.ts】文件中配置

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

const app = createApp(App)
app.use(ElementPlus)

1.2-引入axios

(1)输入命令安装。

npm install axios

(2)新建一个【http.ts】文件,写一个简单的请求封装。
快速掌握Vue3:速成Vue3前端开发看这篇就够啦

//导入axios
import axios from "axios"

//axios.create创建一个axios实例
//我们给这个实例编写配置,后端所有通过这个实例发送请求,都受这个配置约束。
const $http=axios.create({
    baseURL:"http://jsonplaceholder.typicode.com/",
    timeout:1000
});



// 添加请求拦截器
$http.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
  }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  });



// 添加响应拦截器
$http.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response.data;
  }, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  });

export default $http;

(3)新建一个【test.ts】文件进行二次封装。

import $http from "./http"

export const getData=$http.get("/posts");

(3)使用。

<script lang="ts">
import { defineComponent } from 'vue';
import {getData} from "@/apis/test"

export default defineComponent({
  name: 'Home',
  setup(){
      //请求接口
      getData.then((data:any)=>{
        console.log(data);
      })

      return{

      }
    }
});
</script>

1.3-引入vuex

(1)输入命令安装vuex

npm install vuex

(2)在【main.ts】中引入。

import { createApp } from 'vue'
import App from './App.vue'
import store from './store'

createApp(App).use(store).mount('#app')

(3)在src文件夹下新建一个【store/index.ts】文件

import { createStore } from 'vuex'
import app from "./modules/app"
import settings from "./modules/settings"
import user from "./modules/user"

export default createStore({
  // 导入模块
  modules: {
    app,
    settings,
    user
  }
})

(4)【app.ts】格式如下。

//【应用程序模块】
const app={
  //单一状态树,UI可通过this.$store.state.app.*获得数据
  state: {

  },
  //对state数据进行过滤后返回(可以认为是 store 的计算属性)
  getters:{

  },
  // 唯一拥有更改内存数据的接口,不可进行异步操作
  mutations: {

  },
  // 与mutation通讯,UI层写入内存数据的接口,可异步操作
  actions: {

  }
}
export default app;

1.4-引入.env

(1)创建文件xxx.env文件。
快速掌握Vue3:速成Vue3前端开发看这篇就够啦

----------------【.env.development】---------------
#以下的值webpack会根据不同的环境取得不同的值,使用方法:process.env.*
#设定一个标题,代表这个环境是development
NODE_ENV = 'development'

# Base URL
BASE_URL = 'http://xxx:7881' 

# Base API
VUE_APP_BASE_API = 'http://xxx:7881'



----------------【.env.production】---------------
#以下的值webpack会根据不同的环境取得不同的值,使用方法:process.env.*
#设定一个标题,代表这个环境是production
NODE_ENV = 'production'

# Base URL
BASE_URL = 'http://xxx:7881'

# Base API
VUE_APP_BASE_API = 'http://xxx:7881'


----------------【.env.staging】---------------
#以下的值webpack会根据不同的环境取得不同的值,使用方法:process.env.*
#设定一个标题,代表这个环境是development
NODE_ENV = 'development'

# Base URL
BASE_URL = 'http://xxx:7881'

# Base API
VUE_APP_BASE_API = 'http://xxx:7881'

(2)使用。

process.env.VUE_APP_BASE_API

快速掌握Vue3:速成Vue3前端开发看这篇就够啦


1.5-引入cookie

(1)安装。

npm install vue-cookies --save


1.6-引入nprogress

(1)安装。

npm install nprogress -S
npm i @types/nprogress-D

(2) 现在我们对NProgress进行一下简单的封装,首先我们在【common/utils/nporgress.ts】目录下创建文件,然后引入NProgress和CSS样式文件 。
快速掌握Vue3:速成Vue3前端开发看这篇就够啦
(3)内容如下。

import NProgress from 'nprogress' // 进度条
import 'nprogress/nprogress.css' // 进度条样

//全局进度条的配置
NProgress.configure({
  easing: 'ease', // 动画方式
  speed: 1000, // 递增进度条的速度
  showSpinner: false, // 是否显示加载ico
  trickleSpeed: 200, // 自动递增间隔
  minimum: 0.3, // 更改启动时使用的最小百分比
  parent: 'body', //指定进度条的父容器
})

//打开进度条
export const start =()=>{
  NProgress.start();
}

//关闭进度条
export const close =()=>{
  NProgress.done();
}

(4)在【router/index.ts】文件中使用

--引入文件
import { close, start } from '@/common/utils/nprogress'//进度条

--使用
const router = createRouter({
  routes,
  history: createWebHistory(),
})
 
router.beforeEach((pre, next) => {
  start()
})
 
router.afterEach(() => {
  close()
})

1.7-引入Element Plus(按需自动引入)

环境:
快速掌握Vue3:速成Vue3前端开发看这篇就够啦
参考文献:https://www.yisu.com/zixun/723540.html

(1)输入命令安装

npm install element-plus
npm install -D unplugin-vue-components unplugin-auto-import

(2)在【vue.config.ts】中配置。

const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')


// 【每次修改,都需要重新build】
// 插件(module.exports={configureWebpack:[]})
    plugins: [
      AutoImport({
        resolvers: [ElementPlusResolver()]
      }),
      Components({
        resolvers: [ElementPlusResolver()]
      })
    ],

(3)然后执行【npm run dev】报错了(如果报node-sass将这个卸载,安装sass即可)。
快速掌握Vue3:速成Vue3前端开发看这篇就够啦
快速掌握Vue3:速成Vue3前端开发看这篇就够啦
解决: 卸载nodev12,更新到nodev16在重新构建一下项目成功解决 了。
快速掌握Vue3:速成Vue3前端开发看这篇就够啦

命令:
npm uninstall node-sass --dev-S
npm install sass --dev-S


1.8-引入sross-env环境变量配置

(1)安装。

npm i --save-dev cross-env
npm install dotenv-cli --dev-s

(2)创建文件。
快速掌握Vue3:速成Vue3前端开发看这篇就够啦

--【.env.dev.build】
#以下的值webpack会根据不同的环境取得不同的值,使用方法:process.env.*
#设定一个标题,代表这个环境是development
NODE_ENV = production

# Base URL
BASE_URL = 'http://xxx.xxx.xxx:7881' 

# Base API
VUE_APP_BASE_API = 'http://xxx.xxx.xxx:7990'

# 统一认证中心配置
VUE_APP_AUTH_BASEURL = 'http://xxx.xxx.xxx:5021'
VUE_APP_AUTH_LOGIN_RRDIRECTURL = 'http://xxx.xxx.xxx:7881/callback'
VUE_APP_AUTH_LOGOUT_RRDIRECTURL = 'http://xxx.xxx.xxx:7881'


--【.env.dev.serve】
#以下的值webpack会根据不同的环境取得不同的值,使用方法:process.env.*
#设定一个标题,代表这个环境是development
NODE_ENV = development

# Base URL
BASE_URL = 'http://xxx.xxx.xxx:7881' 

# Base API
VUE_APP_BASE_API = 'http://xxx.xxx.xxx:7990'

# 统一认证中心配置
VUE_APP_AUTH_BASEURL = 'http://xxx.xxx.xxx:5021'
VUE_APP_AUTH_LOGIN_RRDIRECTURL = 'http://localhost:7881/callback'
VUE_APP_AUTH_LOGOUT_RRDIRECTURL = 'http://localhost:7881'

(3) 【package.json】中的配置

 "scripts": {
    "dev": "npm run serve:dev",
    "start": "npm run serve:dev",
    "server": "npm run serve:dev",
    "build": "npm run build:dev",
    "serve:dev": "cross-env NODE_ENV=development dotenv -e .env.dev.serve vue-cli-service serve",
    "build:dev": "cross-env NODE_ENV=production  dotenv -e .env.dev.build vue-cli-service build",
    "serve:test": "cross-env NODE_ENV=development dotenv -e .env.test.serve vue-cli-service serve",
    "build:test": "cross-env NODE_ENV=production  dotenv -e .env.test.build vue-cli-service build",
    "serve:prod": "cross-env NODE_ENV=development dotenv -e .env.prod.serve vue-cli-service serve",
    "build:prod": "cross-env NODE_ENV=production  dotenv -e .env.prod.build vue-cli-service build",
    "lint": "vue-cli-service lint"
  },

1.9-引入js-cookie

(1)安装

npm install js-cookie -s
npm install @types/js-cookie --dev-s

(2)封装单独的ts文件。

import Cookies from 'js-cookie'

/*
封装操作Cookie本地存储的方法:
说明:主要用途有保存登录信息。
存储大小:4KB
*/
const cookies = {
  /**
   *设置Cookies
   * @param {String} key 键
   * @param {Object} value 值:存储的值可能是数组/对象,不能直接存储,需要转换 JSON.stringify()
   * @param {Int} expiresTime 过期时间(单位:秒)
   */
  set(key: string, value: any, expiresTime: number) {
    expiresTime=arguments[2] ? arguments[2] : (60*60)*24;//默认值为:24小时
    let expires = new Date(new Date().getTime() * 1 + expiresTime * 1000);
    return Cookies.set(key, value, {
      expires: expires
    });
  },

  /**
   * 获得Cookies
   * @param {String} key 键
   * @return {Object} 根据键取对应的值
   */
  get(key: string) {
    return Cookies.get(key);
  },

  /**
   * 删除Cookies
   * @param {String} key 键
   */
  remove(key: string) {
    return Cookies.remove(key);
  }
};

export default cookies;


1.10-引入el-plus面包屑导航

(1)安装

npm install path-to-regexp -s

(2)写代码。

<template>
  <el-breadcrumb class="app_breadcrumb" separator="/">
    <transition-group name="breadcrumb">
      <el-breadcrumb-item v-for="(item,index) in breadcrumbs" :key="item.path">
        <span v-if="
          item.path === ' ' ||
          item.path === '/' ||
          item.path === '-' ||
          item.redirect === 'noredirect' ||
          index == breadcrumbs.length - 1" class="no_redirect">
          {{item.meta.title}}
        </span>
        <a v-else @click.prevent="handleLink(item)">{{item.meta.title}}</a>
      </el-breadcrumb-item>
    </transition-group>
  </el-breadcrumb>
</template>

<script lang="ts" setup>
import { compile } from 'path-to-regexp'
import { useRouter, useRoute, RouteLocationMatched } from 'vue-router'
import { onBeforeMount, reactive, toRefs, watch } from 'vue'

const route = useRoute();
const router = useRouter();

const pathCompile = (path: string) => {
  const { params } = route;
  const toPath = compile(path);
  return toPath(params);
}

const state = reactive({
  // 面包屑路由
  breadcrumbs: [] as Array<RouteLocationMatched>,

  // 获得面包屑路由
  getBreadcrumb: () => {
    let matched = route.matched.filter((item: RouteLocationMatched) => {
      return item.meta && item.meta.title;
    });
    const first = matched[0];
    if (!state.isIndex(first)) {
        matched = [{ path: '/index', meta: { title: '首页' } } as any].concat(matched);
    }
    state.breadcrumbs = matched.filter(
      (item) => item.meta && item.meta.title
    );
  },

  // 判断是不是首页
  isIndex: (route: RouteLocationMatched):boolean => {
    const name = route && route.name;
    if (!name) {
      return false;
    }
    return (
      name.toString().trim().toLocaleLowerCase() === "Index".toLocaleLowerCase()
    );
  },

  // 跳转路由
  handleLink(item: any){
    const { redirect, path } = item;
    if (redirect) {
      router.push(redirect).catch((err) => {
        console.warn(err);
      })
      return
    }
    router.push(pathCompile(path)).catch((err) => {
      console.warn(err);
    })
  }
});

// 加载
onBeforeMount(() => {
  state.getBreadcrumb();
})

// 监听路由变化
watch(() => route.path, (path: string) => {
  if (path.startsWith('/redirect/')) {
    return;
  }
  state.getBreadcrumb();
})

const { breadcrumbs, handleLink } = toRefs(state);
</script>

<style lang="scss" scoped>
.app_breadcrumb.el-breadcrumb{
  font-size: 14px;
  line-height: 42px;
  height:42px;

  .el-breadcrumb__inner,
  .el-breadcrumb__inner a {
    font-weight: 400 !important;
  }

  .no_redirect{
    color: #c0c4cc;
    cursor: text;
  }
}
</style>

(3)引入组件。

 <breadcrumb class="breadcrumb_container" />

1.11-封装http请求【axios-mapper】

(1)安装需要的依赖

npm install @types/qs
npm install qs

(2)创建【types.ts】
快速掌握Vue3:速成Vue3前端开发看这篇就够啦

// 请求内容类型
export enum ContentType {
  form = 'application/x-www-form-urlencoded',
  json = 'application/json; charset=utf-8',
  multipart = 'multipart/form-data'
}

// 请求方式
export enum Method {
  GET = 'GET',
  POST = 'POST',
  PUT = 'PUT',
  PATCH = 'PATCH',
  DELETE = 'DELETE'
}

// 网络请求参数
export interface RequestParams {
  [key: string]: any
}

(3)创建【convert-model.ts】文件。

// Json-Model相互转换
export class ConvertModel {
  /**
   * @description:  json转model
   * @param {string} json
   * @return {*}
   */
  public static jsonToModel<T>(json: string): T {
    return JSON.parse(json) as T;
  }

  /**
   * @description: model转json
   * @param {any} model
   * @return {*}
   */
  public static modelToJson(model: any): string {
    return JSON.stringify(model);
  }
}

(4)创建【index.ts】文件

import { RequestParams, Method, ContentType } from './types';
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
import { ConvertModel } from './convert-model';

// 导出所有的类型
export * from './types';

export interface HttpClientConfig extends AxiosRequestConfig {
  defaultParams?: RequestParams;
}

// 导出默认请求
export default class HttpClient {
  private _defaultConfig: HttpClientConfig;
  public httpClient: AxiosInstance;

  // 构造函数
  constructor(options: HttpClientConfig = {}){
    this.httpClient = axios.create(options);
    this._defaultConfig = options;
  }

  /**
   * @description: 封装请求类
   * @param {string} path 请求路径 
   * @param {Method} method 请求方式(默认:GET)
   * @param {RequestParams} params 参数
   * @param {ContentType} contentType http配置
   * @param {HttpClientConfig} optionsSource
   * @return {*}
   */
  async request<T>(
    path: string = '',
    method: Method = Method.GET,
    params?: RequestParams,
    contentType: ContentType = ContentType.json,
    optionsSource?: HttpClientConfig
  ):Promise<T> {
    const options: any = Object.assign(
      {},
      this._defaultConfig,
      optionsSource
    );

    const { headers } = options;
    headers['content-type'] = contentType;

    const allParams = Object.assign(
      {},
      this._defaultConfig.defaultParams,
      params
    );

    // 发送请求
    const requestConfig: HttpClientConfig = {
      url: `${path}`,
      method,
      headers,
    };

    if(contentType === ContentType.form) {
      requestConfig.params = allParams;
    } else {
      requestConfig.data =  ConvertModel.modelToJson(allParams);
    }

    return this.httpClient.request(requestConfig)
    .then(res => {
      const data: string = ConvertModel.modelToJson(res.data);
      if (res.status >= 200 && res.status < 300) {
        return ConvertModel.jsonToModel(data) as T;
      } else {
        return Promise.reject(data);
      }
    })
    .catch(async error => {
      return Promise.reject(error);
    })
  };

  // GET请求
  get(url: string, params?: any) {
    return this.httpClient.request({
      url: url,
      method: Method.GET,
      params
    });
  };

  // POST请求
  post(url: string, data?: any) {
    return this.httpClient.request({
      url: url,
      method: Method.POST,
      data
    });
  };

  // PUT请求
  put(url: string, data?: any) {
    return this.httpClient.request({
      url: url,
      method: Method.PUT,
      data
    });
  };

  // Delete请求
  del (url: string, params?: any) {
    return this.httpClient.request({
      url: url,
      method: Method.DELETE,
      params
    });
  };

  // Delete批量请求(Post方式传参)
  del_batch(url: string, data?: any) {
    return this.httpClient.request({
      url: url,
      method: Method.DELETE,
      data
    });
  }
}

(5)使用,封装【https.ts】请求。

import HttpClient, { HttpClientConfig } from '../kimi-axios/index';
import { ElMessage } from 'element-plus';
import { getApiUrl, getToken } from './utils';

const config: HttpClientConfig = {
  baseURL: getApiUrl(),
  headers: {
    'Content-Type': 'application/json;charset=utf-8'
  },
  timeout: 60 * 1000 // 请求超时时间(默认:60秒)
};

const https = new HttpClient(config);
// 请求拦截器
https.httpClient.interceptors.request.use(
  config => {
    // 在发送请求之前做些什么...
    console.log('https:请求拦截器...');

    // // 如果存在Token,让请求携带令牌。
    // var curTime = new Date()
    // var expiretime = new Date(Date.parse(storeTemp.state.user.tokenExpire))
    // // 判断是否存在token,如果存在的话,则每个http header都加上token
    // if (storeTemp.state.user.token && (curTime < expiretime && storeTemp.state.user.tokenExpire)) {
    //   //['Authorization']是一个自定义头密钥,请根据实际情况进行修改。
    //   config.headers['Authorization'] = 'Bearer ' + storeTemp.state.user.token;
    // }

    // ['Authorization']是一个自定义头密钥,请根据实际情况进行修改。
    // config.headers['Authorization'] = 'Bearer ' + store.state.user.kimiToken;
    config.headers = {
      Authorization: `Bearer ${getToken()}`
    };

    return config;
  },
  error => {
    // 处理请求错误...
    return Promise.reject(error);
  }
);

// 响应拦截器
https.httpClient.interceptors.response.use(
  /**
 * 如果您想获取http信息,如标题或状态
 * 请返回response=>response
 */
  /**
 * 通过自定义代码确定请求状态
 * 这里只是一个例子
 * 您还可以通过HTTP状态代码来判断状态
 */
  response => {
    // 自定义错误
    // if(!response.data.success){
    //   Message({
    //     message: response.data.error.message,
    //     type: 'error',
    //     duration: 2 * 1000
    //   })
    // }

    console.log('https:响应拦截器...');
    const res = response;
    return res;
  },
  error => {
    let statusCode = 0;
    try {
      statusCode = error.response.status;
    } catch (e) {
      // 网络请求错误
      if (error.toString().indexOf('Error: Network Error') !== -1) {
        ElMessage({
          message: '您的请求网络发生错误,请稍后重试!',
          type: 'error',
          duration: 2 * 1000
        });
        return Promise.reject(error);
      }
    }

    // 超时请求处理
    var originalRequest = error.config;
    if (error.code === 'ECONNABORTED' && error.message.indexOf('timeout') !== -1 && !originalRequest._retry) {
      ElMessage({
        message: '您的请求超时,请稍后重试!',
        type: 'error',
        duration: 2 * 1000
      });
      originalRequest._retry = true;
      return Promise.reject(error);
    }

    // 根据状态码处理
    if (statusCode) {
      if (statusCode === 401) {
        // 401:未登录
        ElMessage({
          message: '您当前未登录,请先登录!',
          type: 'error',
          duration: 2 * 1000
        });
      } else if (statusCode === 403) {
        // 403:无权限
        ElMessage({
          message: '您访问的权限等级不够,拒绝访问!',
          type: 'error',
          duration: 2 * 1000
        });
      } else if (statusCode === 429) {
        // 429:IP限流
        ElMessage({
          message: '您刷新次数过多,请稍后重试!',
          type: 'error',
          duration: 2 * 1000
        });
      } else if (statusCode === 500) {
        // 500:自动错误&&系统自定义错误
        if (!error.response.data.success && error.response.data.result === 'error_constom') {
          ElMessage({
            message: error.response.data.error.message,
            type: 'error',
            duration: 2 * 1000
          });
        } else {
          ElMessage({
            message: '对不起,在处理您的请求期间,产生了一个服务器内部错误!',
            type: 'error',
            duration: 2 * 1000
          });
        }
      } else {
        // 其他
        let errorMsg = '';
        switch (statusCode) {
        case 400:
          errorMsg = '请求报文中存在语法错误!';
          break;
        case 404:
          errorMsg = '服务器找不到请求的接口!';
          break;
        case 405:
          errorMsg = '请求类型出错!';
          break;
        case 408:
          errorMsg = '请求超时!';
          break;
        case 415:
          errorMsg = '请重新登录!';
          break;
        case 501:
          errorMsg = '服务未实现!';
          break;
        case 502:
          errorMsg = '服务器作为网关或代理,从上游服务器收到无效响应!';
          break;
        case 503:
          errorMsg = '服务不可用!';
          break;
        case 504:
          errorMsg = '服务器连接超时!';
          break;
        case 505:
          errorMsg = 'HTTP版本不受支持!';
          break;
        default:
          errorMsg = '其他错误!';
        }
        ElMessage({
          message: errorMsg,
          type: 'error',
          duration: 3 * 1000
        });
      }
    } else {
      ElMessage({
        message: '您的接口请求失败,请稍后重试!',
        type: 'error',
        duration: 2 * 1000
      });
    }
    return Promise.reject(error);
  }
);

export default https;

1.12-引入全局loading

(1)element-plus需要在【main.ts】中先单独引入loading样式。

// 引入loading样式
import 'element-plus/theme-chalk/el-loading.css';

(2)新建【loading.ts】文件全局使用。

// 【全局 Loading】:以服务的方式调用的全屏 Loading 是单例的。
import { ElLoading } from 'element-plus'

export default function() {
  const loading = (title: string) => {
    const loadingInstance = ElLoading.service({ 
      lock: true,
      text: title,
      background: 'rgba(0, 0, 0, 0.7)',
    });
    return loadingInstance;
  };

  return {
    loading
  }
}

(3)使用。

// 导入
import Loading from '@/utils/loading';

//启用
const loadingInstance = loading('登录中...');

//关闭
loadingInstance.close();

原创地址:https://www.cnblogs.com/kimiliucn/p/17605624.html文章来源地址https://www.toymoban.com/news/detail-646911.html

到了这里,关于快速掌握Vue3:速成Vue3前端开发看这篇就够啦的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Git、GitHub、Gitee快速上手,看这篇就够了

      目录 第1章  Git 概述 1.1 何为版本控制 1.2 为什么需要版本控制 1.3 版本控制工具 1.4 Git 简史   1.5 Git 工作机制   1.6 Git 和代码托管中心 第2章 Git 安装 第 3 章 Git 常用命令 3.1 设置用户签名 3.2 初始化本地库 3.3 查看本地库状态   3.3.1 首次查看(工作区没有任何文件) 3.3.2 新

    2024年02月03日
    浏览(35)
  • C入门语言看这篇就够了,教你快速上手C语言

      哈喽,各位铁汁们好啊!✨今天来给大家带来的是初识 C语言 里面的 转义字符 和 注释 。   《入门C语言篇》主要带大家简单认识-一下C语言,俗话说 没吃过猪肉,也见过猪跑。 带大家了解下C语言。可以读懂C语言的简单程序,后面博主会给大家出《C语言初级》加进阶

    2024年02月13日
    浏览(34)
  • 快速掌握WebSocket:仅需10分钟的速成教程!

    WebSocket是一种在客户端和服务器之间实现双向通信的网络协议。它通过在单个TCP连接上提供全双工通信功能,使得服务器可以主动向客户端推送数据,而不需要客户端发起请求。 与传统的HTTP协议相比,WebSocket具有以下几个显著的区别: 双向通信 :WebSocket支持客户端和服务器

    2024年02月20日
    浏览(36)
  • 【vue3】13-前端路由-Vue-Router的详解: 从入门到掌握

    路由其实是网络工程中的一个术语: 在 架构一个网络 时,非常重要的两个设备就是 路由器和交换机 。 当然,目前在我们生活中 路由器 也是越来越被大家所熟知,因为我们生活中都会用到 路由器 : 事实上, 路由器 主要维护的是一个 映射表 ; 映射表 会决定数据的流向; 路由

    2024年02月09日
    浏览(34)
  • uniapp Android原生插件开发和离线打包调试看这篇就够了!(保姆级手把手教学)

    此文章最适合第一次开发原生插件并且无原生开发经验的攻城狮! uni-app 官方文档地址:uni原生插件开发教程 原生插件必备离线SDK下载:Android 离线SDK - 正式版 要拥有JAVA环境 jdk1.8 版本,其他版本根据情况自我调整 想必读者在看此文章之前电脑就有HBuilderX和Android Studio开发工

    2024年02月10日
    浏览(42)
  • Vue3+SpringBoot快速开发模板

    起因:个人开发过程经常会使用到Vue3+SpringBoot技术栈来开发项目,每次在项目初始化时都需要涉及一些重复的整理工作,于是结合一些个人觉得不错的前后端模板进行整合,打通一些大多数项目都需要的实现的基础功能,以便于快速开发项目。代码已按个人力所能及的规范编

    2024年02月14日
    浏览(23)
  • 【前端开发工具】VUE3 devtools安装

    尤雨溪在2020年9月19日晚正式发布vue3.0 one piece。此版本相较于vue2版本,更快、更小、更易维护、更易于原生、让开发者更轻松;所以学习vue3,对于一个前端开发者来说是一个刻不容缓的学习趋势。 学习vue3自然也离不开debug啦~~ Vue官方发布了调试工具Vue-Devtools。 VUE3的Vue-Devt

    2024年02月05日
    浏览(36)
  • 从Vue2到Vue3, 一键升级前端开发技能

    本文的目的,是为了让已经有 Vue2 开发经验的   人   ,快速掌握 Vue3 的写法。 因此,   本篇假定你已经掌握 Vue 的核心内容   ,只为你介绍编写 Vue3 代码,需要了解的内容。 首先,Vue3 新增了一个叫做组合式 api 的东西,英文名叫 Composition API 。因此 Vue3 的  script  现在支

    2024年02月08日
    浏览(61)
  • 「Vue|网页开发|前端开发」01 快速入门:用vue-cli快速写一个Vue的HelloWorld项目

    本文主要介绍如何用vue开发的标准化工具vue-cli快速搭建一个符合实际业务项目结构的hello world网页项目并理解vue的代码文件结构以及页面渲染流程。 Windows 系统的 node.js 安装十分简易,没有环境安装经验的伙伴可以参考文章:Windows系统下安装node.js 我们需要先创建一个用于放

    2024年02月12日
    浏览(37)
  • Vue3前端开发,computed计算属性的基础练习

    Vue3前端开发,computed计算属性的基础练习! 在新版里面,和传统的vue2一样,计算属性,都是对一些数据运算进行了封装操作。返回结果是一个实时监控的效果。区别在于,写法不同。效果是一样。 下面给大家展示一个简单的案例。 如图,自定义一个组件,ComputedDemo.vue。里

    2024年01月18日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包