axios的二次封装 - 配置一个axios
api-config.js
JavaScript
import axios from "axios";
axios.defaults.baseURL="http://localhost:3000";
axios.interceptors.request.use(
config=>{
console.log("请求拦截器1调用成功");
return config;
},
function(error){
console.log("请求拦截器1调用失败");
return Promise.reject(error)
}
)
//这个是设置响应拦截器的api,第一个成功回调,第二个失败回调
axios.interceptors.response.use(
function(response){
console.log("响应拦截器1调用成功");
return response;
},
function(error){
console.log("响应拦截器1调用失败");
return Promise.reject(error);
}
)
export default axios;
api-request.js
JavaScript
import axios from "./config";
// 向/goodList发送get请求
export function getGoodList(){
return axios({
// http://localhost:3000/goodList
url:'/goodList',
method:"get"
})
}
Index.vue 调用请求
JavaScript
async function getData(){
// 原来调用方式
// let {data} = await axios({
// url:"http://localhost:3000/goodList",
// method:"get"
// })
// console.log(data);
// 封装后调用方式
let data = await getGoodList();
console.log(data);
}
onMounted(()=>{
getData()
})
axios的二次封装 - 配置多个axios
api/config.js
JavaScript
import axios from "axios";
// 配置的json-server
const http = axios.create({
baseURL: 'http://127.0.0.1:3001',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
http.interceptors.request.use(
config=>{
console.log("json-server请求拦截器");
return config;
},
function(error){
console.log("请求拦截器1调用失败");
return Promise.reject(error)
}
)
// 配置nodejs
const httpnode = axios.create({
baseURL: 'http://127.0.0.1:3000',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
httpnode.interceptors.request.use(
config=>{
console.log("httpnode请求拦截器");
return config;
},
function(error){
console.log("请求拦截器1调用失败");
return Promise.reject(error)
}
)
export {
http,
httpnode
}
api/request.js
JavaScript
import { http,httpnode } from "./configAll";
// 获取goodsList中的数据
export function goodList(){
return http({
url:"/goodList",
method:"get"
})
}
// 获取nodejs中的数据
export function goodFloower(){
return httpnode({
url:"/hua/getFloower",
method:"get"
})
}
index.vue调用方法
HTML
<script setup>
import TabBar from "@/components/global/common/TabBar.vue"
import { goodList,goodFloower } from "../../api/requestAll";
import { onMounted } from "vue";
onMounted(async()=>{
// 获取json-serve染数据
let data = await goodList();
console.log(data);
// 获取nodejs中的数据
let datanode = await goodFloower();
console.log(datanode);
})
</script>
扩展:参考企业axios封装
请求封装
![[b5b9288a-836d-44e7-92a2-78a50feb70c9.png]]
响应封装
![[2d4a8c59-ecb1-47fb-8a87-418ef0a5d42c.png]]
深拷贝
什么是****深拷贝
在Javascript中,对象的复制有两种方式: 浅拷贝和深拷贝。 浅拷贝只拷贝内存地址,拷贝后的对象和原始对象引用同一个地址,所以修改拷贝后的对象会影响到原始对象。
深拷贝是指将一个对象完全复制到另一个对象中,包括对象的所有属性和方法。与浅拷贝不同,深拷贝会递归地复制对象的所有属性和方法,直到所有属性和方法都被复制完毕。因此,深拷贝可以保证复制后的对象与原始对象完全独立,互不影响。
如何实现****深拷贝
- 使用扩展运算符
只能实现第一层的深拷贝,不能实现深层级对象的深拷贝
JavaScript
//--------------------------------------数组
let arr1 = [2, 5, 6]
let arr2 = arr1 // 浅拷贝
let arr3 = [...arr1] //深拷贝
//---------------------------------------对象
// *************************demo1
//浅拷贝
// let obj1 = { a: 1, b: 2 };
// let obj2 = obj1
// obj2.a = 10
// console.log(obj1.a); //10
//深拷贝
// let obj1 = { a: 1, b: 2 };
// let obj2 = {...obj1} // obj2 = { a: 1, b:2}
// obj2.a = 10
// console.log(obj1.a); // 1
// *************************demo2
//浅拷贝
let obj1 = { a: { c: 1 }, b: 2 };
let obj2 = {...obj1}
obj2.a.c = 10
console.log(obj1.a.c); //10
- 使用 Object.assign()
object.assign()主要用于对象合并,将源对象中的属性复制到目标对象中,他将返回目标对象。 同扩展运算符一样,只能实现对象第一层的深拷贝
JavaScript
//深拷贝
// let obj1 = { a: 1, b: 2 };
// let obj2 = Object.assign({},obj1)
// obj2.a = 10
// console.log(obj1.a); // 1
//浅拷贝
let obj1 = { a: { c: 1 }, b: 2 };
let obj2 = Object.assign({},obj1)
obj2.a.c = 10
console.log(obj1.a.c); //10
- JSON.parse(JSON.stringify())
这种方式简单易用,大部分情况可用
JavaScript
let obj = { a: { b: 1 } };
let clone = JSON.parse(JSON.stringify(obj));clone.a.b = 2;console.log(obj.a.b); // 1
缺点 (自行了解) 参考 https://blog.csdn.net/m0_54566205/article/details/129561012
-
无法处理函数和 undefined
-
无法处理循环引用
-
无法处理一些特殊对象,如 RegExp、Error、Date 等,这些对象会被转换成空对象
-
对象的原型链上的属性会丢失
-
使用****递归 (最重要)
JavaScript
var obj = {
a: 1,
b: [1, 2, 3],
c: {
c1: 1
}
}
function deepClone(obj) {
//如果不是对象,直接返回
if (obj === null || typeof obj !== "object") return obj;
//判断是不是数组
let clone = Array.isArray(obj) ?[] : {};
for (let key in obj) {
//判断key是不是自身的属性而不是原型的
if (obj.hasOwnProperty(key)) {
//递归
clone[key] = deepClone(obj[key])
}
}
return clone
}
let obj1 = deepClone(obj);
obj1.b.push(4);
console.log(obj.b, obj1.b);//[1,2,3] [1,2,3,4]
- 使用 lodash 的 _.cloneDeep()
Lodash 提供了深拷贝方法 _.cloneDeep(),我们可以直接使用:
JavaScript
let obj = { a: { b: 1 } };
let clone = _.cloneDeep(obj);
clone.a.b = 2;console.log(obj.a.b); // 1
菜单的滚动效果
better-scroll网站:https://better-scroll.github.io/docs-v1/doc/zh-hans/options.html
业务逻辑-js部分
HTML
<script setup>
// 引入底部tabbar
import TabBar from '@/components/global/common/TabBar.vue';
import { nextTick, onMounted, ref } from 'vue';
import { getGoods } from '../../api/request';
import BScroll from 'better-scroll';
let goods = ref([]);
let curIndex = ref(0);
let foodList = ref([]);
let listHeight = ref([]);
let menuScroll;
let foodScroll;
let timer;
async function init(){
let {data} = await getGoods();
goods.value = data;
// console.log(data);
nextTick(()=>{
menuScroll = new BScroll(".left",{
click:true // 滚动
})
foodScroll = new BScroll(".right",{
probeType:2, // 绑定事件,获取定位
click:true
})
// 获取所有高度
listHeight = foodList.value.map(item=>item.offsetTop)
// 给foodScroll绑定滚动事件
foodScroll.on("scroll",pos=>{
// 防抖效果
clearInterval(timer);
timer = setTimeout(()=>{
// console.log(pos);
// 滚动效果
getIndex(pos);
},300)
})
})
}
function getIndex(pos){
let y = Math.abs(pos.y);
let len = listHeight.length;
let index;
for(let i=0;i<len-1;i++){
if(y>=listHeight[i] && y<listHeight[i+1]){
index = i;
break;
}
}
if(index === undefined){
index = len - 1;
}
curIndex.value = index;
}
onMounted(()=>{
init();
})
function toggle(index){
// 变成红色背景
curIndex.value = index;
// 点击左侧,右侧内容滚动
foodScroll.scrollToElement(foodList.value[index],800);
}
</script>
页面布局-template
HTML
<template>
<div class="car">
<h1>购物车页面</h1>
<div class="order">
<div class="left">
<ul>
<li
@click="toggle(index)"
v-for="(item,index) in goods"
:key="index"
:class="curIndex == index ? 'active':''"
>{{item.name}}</li>
</ul>
</div>
<div class="right">
<ul>
<li v-for="(item,index) in goods" ref="foodList">
<p>{{item.name}}</p>
<ul>
<li v-for="(sitem,sindex) in item.foods">
<img :src="sitem.image" alt="">
<div class="text">
<p>名称:{{sitem.name}}</p>
<p>价格:{{sitem.price}}</p>
</div>
</li>
</ul>
</li>
</ul>
</div>
</div>
<!-- tabbar -->
<TabBar></TabBar>
</div>
</template>
页面样式-css
HTML
<style lang="scss" scoped>
.car{
height: 900px;
.jxhw{
height: 100px;
background-color: red;
margin-top: 50px;
}
}
.order{
// 弹性盒子
display: flex;
position: absolute;
top: 80px;
bottom: 0;
left: 0;
right: 0;
background-color: #eee;
.left{
width: 120px;
background-color: #aaa;
// overflow: scroll;
overflow: hidden;
li{
padding: 5px;
margin: 5px;
height: 50px;
border: 1px solid #eee;
}
}
.active{
background-color: red;
}
.right{
// flex 是 flex-grow[放大比例]、flex-shrink【缩小比例】、flex-basis【剩余空间分配】的缩写
flex: 120px 1;
background-color: #fff;
overflow: hidden;
&>ul>li{
&>p{
height: 30px;
border: 1px solid #aaa;
}
ul li{
height: 70px;
border: 1px solid #eee;
margin: 10px;
display: flex;
padding: 10px;
img{
width: 50px;
height: 50px;
}
}
}
}
}
</style>
vue.config.js的配置
- 认识vue.config.js
-
vue-cli@5 会自动创建vue.config.js
-
vue.config.js是一个可选的配置文件,如果项目的 (和package.json同级的) 根目录中存在这个文件,那么它会被@vue/cli-service自动加载。 从vue-cli3开始的一些服务配置都迁移到CLI Service里面了,对于一些基础配置和一些扩展配置需要在根目录新建一个vue.config.js文件进行配置
- 常用配置
特别特别需要注意的是只要vue.config.js进行了修改,就必须重启
vue.config.js
JavaScript
const path = require('path')
// 工具函数,添加绝对路径
// dir: "./src/components" ---- "E:/share/myapp/src/components"
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
lintOnSave: false,// 禁用eslint检查
//设置路径别名
chainWebpack(config) {
config.resolve.alias
//用com这个别名代表./src/components的完整路径
.set('com', resolve('./src/components'))
}
}
- 在vue项目开发阶段实现跨域
如果后端没有设置cors,实现开发阶段跨域就需要在vue.config.js进行服务器代理的配置
- 去掉后端跨域的代码
JavaScript
//去掉以下代码
const cors = require("cors")
app.use(cors())
- 在config.js中修改baseURL
Plain
//原设置
baseURL: 'http://localhost:3000'
//修改为
baseURL: '/api'
- 在vue.config.js的添加proxy代理
JSON
devServer: {
open: true, // 配置自动启动浏览器
proxy: {
'/api': {
target: "http://localhost:3000/", //访问的服务器地址
changeOrigin: true,
ws: true, //启用websocket
pathRewrite: {
'^/api': '' //替换规则
}
},
'/admin': {
target: "http://xx.xxx.xxx.xxx/",
changeOrigin: true,
ws: true,
pathRewrite: {
'^/admin': ''
}
}
}
}