乐趣区

关于前端:离职成功上岸的一些面试考点总结

HTML5

新个性

语义化标签:header, footer, article, section, nav, menu, hgroup 等
更多的 HTML5 表单个性,例如 calendar、date、time、email、url、search,
反对 Video
新增 Local Storage,应用 Local Storage 能够永恒存储大的数据片段在客户端(除非被动删除),目前大部分浏览器曾经反对

挪动端适配计划

  1. viewport 缩放计划

    在写 HTML、CSS 对设计稿进行还原时不关注屏幕尺寸的差别,而是间接按设计稿的标注来开发。比方设计稿里标注的文字字号是 30px,CSS 里就设置文字字号 30px。

    页面开发好后,在 HTML 的 head 标签里退出 <meta name="viewport" content="width={设计稿宽度}, initial-scale={屏幕逻辑像素宽度 / 设计稿宽度}" >。通过 js 动静计算屏幕的逻辑像素宽度,

    initial-scale:网页初始缩放值

  2. 动静 rem 计划

    在应用单位管制页面元素大小时,能够应用固定单位 px,也能够应用绝对单位 rem。2rem 等于 html 标签 font-size 的 2 倍。

    基于这个原理,对于须要适配屏幕等比缩放的元素能够选用 rem 作为单位,对于不须要等比缩放的元素仍旧应用 px 作为单位。

    只有调整 html 标签的 font-size,就能让所有应用 rem 单位的元素跟随着发生变化,而应用 px 单位的元素不受影响。

    插件:postcss

    例如:设计师交付的设计稿宽度是 750px,设计稿上一个 div 的标注尺寸是 375px(宽度是设计稿宽度的一半)。咱们能够

    • 设置 html 的 font-size 为 100* 屏幕宽度 / 设计稿宽度
    • 在写 CSS 时设置 div 的宽度是 3.75rem(计算时用设计稿标注值除以 100),边框宽度为 1px

    假如用户在逻辑像素宽度是 375px 的设施上关上页面,则 html 的 font-size 是 100*375/750 = 50px,div 的宽度是 3.75rem,即 187.5px 正好是屏幕宽度的一半。

    假如用户在逻辑像素宽度是 428px 的设施上关上页面,则 html 的 font-size 是 100*428/750 = 57.07px,div 的宽度是 3.75rem,即 214px 正好是屏幕宽度的一半。

    注:font-size= 100 只是为了不便就是,事实上能够取任意值

    <script>
        const WIDTH = 750  // 如果是尺寸的设计稿在这里批改
        const setView = () => {
          // 设置 html 标签的 fontSize * 屏幕宽度 / 设计稿宽度
          document.documentElement.style.fontSize = (100*screen.width/WIDTH) + 'px'
        }
        window.onresize = setView; // 如果窗口大小产生扭转,就触发 setView 事件
        setView()
    </script>
  1. vm 适配计划

    vw 是绝对单位,1vw 示意屏幕宽度的 1%。基于此,咱们能够把所有须要适配屏幕大小等比缩放的元素都应用 vw 作为单位。不须要缩放的元素应用 px 做单位。

  2. 媒体查问

    应用 css media 工具不同的屏幕大小适配不同的款式

盒子模型

规范盒子模型:(box-sizing:content-box;)

padding 和 border 不被蕴含在定义的 width 和 height 之内,对象的理论宽度等于设置的 width 值和 border、padding 之和

IE 盒子模型:(box-sizing:border-box;)

padding 和 border 被蕴含在定义的 width 和 height 之内。对象的理论宽度就等于设置的 width 值,即便定义有 border 和 padding 也不会扭转对象的理论宽度

CSS3

新增的一些个性

圆角 border-radius,暗影 box-shadow,文字暗影 text-shadow,

线性突变(gradient),旋转(transform)

媒体查问(@media),多栏布局(colums)

边框图片:border-image

CSS3 动画

产考

https://zhuanlan.zhihu.com/p/…

css 三栏布局(圣杯布局), 左右固定宽度, 两头自适应

相对定位法

原理是将左右两边应用 absolute 定位,因为相对定位使其脱离文档流,前面的 middle 会天然流动到他们下面,而后应用 margin 属性,留出左右元素的宽度,既能够使两头元素自适应屏幕宽度。

<div class="main">
    <div class="left">left</div>
    <div class="middle">middle</div>
    <div class="right">right</div>
</div>

本身浮动法

原理就是对左右别离左浮动和右浮动,float 使左右两个元素脱离文档流,两头元素失常在失常文档流中。对两头文档流应用 margin 指定左右外边距进行定位。

该布局法的有余是三个元素的程序,middle 肯定要放在最初,middle 占据文档流地位,所以肯定要放在最初,左右两个元素地位没有关系。当浏览器窗口很小的时候,左边元素会被挤到下一行。

<div class="main">
    <div class="left">left</div>
    <div class="right">right</div>
    <div class="middle">middle</div>
</div>

flex 布局法

原理就是为父元素增加款式 display:flex,左右固定宽度,两头设置 flex:1,middle 肯定要放在两头

<div class="main">
    <div class="left">left</div>
    <div class="middle">middle</div>
    <div class="right">right</div>
</div>

Css 浏览器兼容

依据不同的浏览器内核增加不同的 css 前缀

Chrome 内核 之前 Webkit,已改 Blink 内核

FireFox 火狐 内核 Gecko

Ssfari 苹果 内核 Webkit

IE 浏览器 内核 Trident

Opera 欧朋 内核 现已改用 Google Chrome 的 Blink 内核

-moz- 火狐浏览器
-Webkit- safari 谷歌浏览器等应用 Webkit 引擎的浏览器
-o- Opera 浏览器(晚期)
-ms- IE

实现垂直居中

对已知高度块级元素进行垂直居中

  1. 相对定位,配合 top:50% 和负 margin-top(元素高度一半)进行垂直居中
.content{
  position: absolute;
  top: 50%;
  left: 50%;
  margin-top: -10em; /* 为元素 height/2 */
  margin-left: -10em;
  width: 20em;
  height: 20em;
  background-color: aqua;
}
  1. 相对定位,配合 top:0;bottom:0; 和 margin:auto 进行垂直居中
.content{
  position: absolute;
  margin:auto;top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  height: 200px; /* 要求指明元素高度 */
  background-color: aqua;
}
  1. 设置 position:absolute; 和 calc()函数实现垂直居中

    .content{
        position: absolute;
        top:calc(50% - 10em); /*calc(50% - 元素自身高度一半)*/
        left: calc(50% - 20em); /* 留神应用时减号间有空格 */
        width: 40em;
        height: 20em;
        background-color: aqua;
    }

对未知高度块级元素进行垂直居中

  1. 设置 position:absolute;和 transform:traslate(x,y)实现程度垂直居中

    .content{
      position: absolute;
      margin:auto;top: 50%;
      left: 50%;
      transform:translate(-50%,-50%); /* 针对元素自身向左以及向上挪动 50%*/
      background-color: aqua;
    }
  2. 基于 flex 的解决方案

    .parent{
      display: flex;
      background-color: beige;
    }
    
    .content{
      margin: auto; /* 主动绝对于父元素程度垂直居中 */
      background-color: aqua;
    }
    
    

flex 1 到底是什么

flex 实际上是 flex-grow、flex-shrink 和 flex-basis 三个属性的缩写。

flex:1 ==> flex:1 1 auto

flex-grow:属性指定了 flex 容器中残余空间的多少应该被调配给我的项目。flex-grow 设置的值为扩张因子,默认为 0,残余空间将会依照这个权重别离调配给子元素我的项目。

flex-shrink:属性指定了 flex 元素的膨胀规定。flex 元素仅在默认宽度之和大于容器的时候才会产生膨胀。默认属性值为 1,所以在空间不够的时候,子项目将会主动放大。

flex-basis:属性指定了 flex 元素在主轴方向上的初始大小。如果不应用 box-sizing 扭转盒模型的话,那么这个属性就决定了 flex 元素的内容的尺寸。如果设置了 flex-basis 值,那么元素占用的空间为 flex-basis 值;如果没有设置或者设置为 auto,那么元素占据的空间为元素的 width/height 值。

参考

flex 罕用属性

flex-direction:主轴的方向(即我的项目的排列方向)

  • row(默认值):主轴为程度方向,终点在左端。
  • row-reverse:主轴为程度方向,终点在右端
  • column:主轴为垂直方向,终点在上沿。
  • column-reverse:主轴为垂直方向,终点在下沿。

flex-wrap 属性:(轴线)

  • flex-wrap: nowrap | wrap | wrap-reverse;

justify-content 属性:定义了我的项目在主轴上的对齐形式。

  • justify-content: flex-start | flex-end | center | space-between | space-around;

align-items 属性:定义我的项目在穿插轴上如何对齐。

  • align-items: flex-start | flex-end | center | baseline | stretch;

align-content 属性:定义了多根轴线的对齐形式。如果我的项目只有一根轴线,该属性不起作用。

  • align-content: flex-start | flex-end | center | space-between | space-around | stretch;

flex-grow 属性:定义我的项目的放大比例,默认为 0,即如果存在残余空间,也不放大

  • flex-grow: <number>; / default 0 /

JS

var、let、const 的区别?

var 申明的变量有变量晋升的个性,而 let、const 没有

同一作用域下 let 和 const 不能反复申明同名变量,而 var 能够

var 申明的变量会挂载到 windows 对象上,所以应用 var 申明的是全局变量

const 申明的是常量,必须赋初值,一旦申明不能再次赋值批改,如果申明的是复合类型数据,能够批改其属性

js 中的数据类型

根底类型:number,string,null,undefiend,boolean,symbol

援用类型:Object,Function,Date,RE 正则

=== 与 ==

== 在比拟类型不同的变量时,会进行数据类型转化,将二者转换成数据类型雷同的变量,再进行比拟。

=== 比拟的二者数据类型不一样时,间接返回 false。

判断某个属性是否存在对象中

in 运算符:如果指定的属性在指定的对象或其原型链中,则 in 运算符返回 true。

hasOwnProperty(key):示意是否有本人的属性。这个办法会查找一个对象是否有某个属性,然而不会去查找它的原型链。

Object.key():获取对象所有的 key,返回一个数组,可判断属性是否存在数组中

判断 this 指向?箭头函数的 this 指向什么?

一般函数:一般函数 this 指向默认 window,严格模式下 this 为 undefiend

在构造函数以及类中的 this:构造函数和类须要配合 new 应用, 而 new 关键字会将构造函数中的 this 指向实例对象,所以 this 指向 实例对象。

绑定事件函数的 this:谁调用就指向谁。

在箭头函数中:箭头函数没有本人的 this,会继承其父作用域的 this。

call apply bind 的作用与区别?

作用:扭转函数外部 this 的指向

区别:

  1. call 和 apply 会调用函数,而 bind 不会调用
  2. call 和 bind 传递参数为 一一传入,而 apply 的参数必须为数组模式

什么是闭包?

闭包是指可能拜访另一个函数作用域中的变量的一个函数。在 js 中,只有函数外部的子函数能力拜访局部变量,所以闭包能够了解成“定义在一个函数外部的函数”。

闭包的作用
利用闭包能够冲破作用链域,将函数外部的变量和办法传递到内部,让内部函数能够拜访到外部函数的变量和办法

闭包的长处
失常的函数,在执行完之后,函数外面申明的变量会被垃圾回收机制解决掉。然而造成闭包的函数在执行之后,不会被回收,仍旧存在内存中。

闭包的毛病
因为变量不会被回收,所以内存中始终存在,消耗内存。

JS 同步与异步

同步工作是指在主线程上排队执行的工作,只有前一个工作执行结束,能力继续执行下一个工作。

异步工作指的是,不进入主线程、而进入 ” 工作队列 ” 的工作,只有等主线程工作执行结束,” 工作队列 ” 的工作才会进入主线程执行。

如何开启异步工作

  1. 回调函数

    setTimeout(() => {
        // f1 的工作代码
        callback();},1000)
  1. 事件监听.

    实现原理也是利用定时器的原理去把函数放入事件队列里,等全副执行结束之后,才会执行事件队列里的办法

  1. 公布 / 订阅

    在 Vue 中能够应用 EventBus 来作为沟通桥梁的概念,就像是所有组件共用雷同的事件核心,能够向该核心注册发送事件或接管事件

    // 事件注册
    EventBus.$emit("事件", '参数');
    // 事件监听
    EventBus.$on("事件", e => {console.log('回调函数')
    });
    // 敞开事件
    EventBus.$off("事件",{console.log('回调函数')
    })
  1. Promises

    简略说,它的思维是,每一个异步工作返回一个 Promise 对象,该对象有一个 then 办法,容许指定回调函数。比方,f1 的回调函数 f2, 能够写成:f1().then(f2);

  1. async await 语法糖

    async 润饰的办法会返回一个 promises 对象

    await 只能放在被 async 润饰的函数内。能够了解为 期待

    await 润饰的如果是 Promise 对象:能够获取 Promise 中返回的内容(resolve 或 reject 的参数),且取到值后语句才会往下执行;

    如果不是 Promise 对象:把这个非 promise 的货色当做 await 表达式的后果。

Promise

promise 有三个状态:

  1. Pending(进行中)
  2. Resolved(已实现)
  3. Rejected(已回绝)

promise 的状态一旦产生扭转就注定后果,不可逆转,通过 new Promise()来应用 promise

当 Promise 执行胜利后会执行 resolved()函数,通过 then 回调返回后果,后果就是 resolve()的参数,then 返回的也是一个 Promise 对象,能够链式调用

当 Promise 外部产生谬误后会执行 rejected()函数,通过 catch 处理错误音讯,

Promise 的其余办法

promise.all()传入一个数组,当所有事务都解决实现之后再返回后果,例如通过 all 去申请一系列 api,所有 api 返回后果后 promise 才调用 resolve 回调,返回一个数组

promise.race()传入一个数组,当其中一个事务处理实现后就回返回后果,

JS 事件循环

js 是单线程的脚本语言,同一时间只能做同一件事,以至于执行工夫比拟长的代码就会产生阻塞,为了解决这一问题,js 将代码执行的模式分为两种,同步和异步:

  • 同步模式: 就是前一个工作执行实现后,再执行下一个工作,程序的执行程序与工作的排列程序是统一的、同步的;
  • 异步模式: 则齐全不同,每一个工作有一个或多个回调函数(callback),前一个工作完结后,不是执行队列上的后一个工作,而是执行回调函数;后一个工作则是不等前一个工作的回调函数的执行而执行,所以程序的执行程序与工作的排列程序是不统一的、异步的。

事件循环:

  1. 执行全局 Script 同步代码,这些同步代码有一些是同步语句,有一些是异步语句(比方 setTimeout 等)(这个过程中触发的回调函(比方 resolve,)数进入宏 / 微队列);
  2. 全局 Script 执行结束(执行栈清空),
  3. 执行微工作队列(微工作进入执行栈),直到微工作队列清空(留神,如果在执行 microtask 的过程中,又产生了 microtask,那么会退出到队列的开端,也会在这个周期被调用执行;)
  4. 取出宏队列队首的工作,进入执行栈;
  5. 执行宏工作(宏工作执行过程中可能产生新的宏工作或微工作,别离入队列,宏队列可能不为空,进入宏队列队尾)
  6. 如此重复循环,直到所有工作清空(执行栈清空)

同步工作,宏工作,微工作:

  • 同步工作:script(整体代码)
  • 宏工作:setTimeout,setInterval,setImmediate(node 中),I/O (比方 Ajax 操作从网络读取数据),UI render(渲染)
  • 微工作:process.nextTick,Promise,Async/Await(理论就是 promise),MutationObserver(html5 新个性)
// 执行 setTimeout
setTimeout(() => {
      // 向宏工作外面增加一个工作
    console.log(1);
}, 0)
// 执行同步代码并输入
console.log(2);
// 执行 Promise
new Promise((resolve, reject) => {
  // 执行同步代码并输入
    console.log(3);
  // 向微队列外面增加一个工作
    resolve(4)
}).then(e => {
  // 执行微工作
    console.log(e);
})
// 执行同步代码并输入
console.log(5); // 后果:2,3,5,4,1

JS new 一下会产生什么?

如果有一个构造函数 Foo(){…}

当代码 new Foo(…) 执行时,会产生以下事件:

  1. 一个继承自 Foo.prototype 的新对象被创立。
  2. 应用指定的参数调用构造函数 Foo,并将 this 绑定到新创建的对象。new Foo 等同于 new Foo(),也就是没有指定参数列表,Foo 不带任何参数调用的状况。
  3. 由构造函数返回的对象就是 new 表达式的后果。如果构造函数没有显式返回一个对象,则应用步骤 1 创立的对象。(个别状况下,构造函数不返回值,然而能够手动 return 返回对象,来笼罩失常的对象创立步骤)

JS 原型链

例如:定义一个 person 对象

let person = {
    name:"",
    age:30
    ...
}

person 对象并没有 toStringvalueOf 等办法,然而能够调用,因为当对象在调用办法的时候,如果对象上没有定义,就回去 obj.prototype 或者 __ prop__ 里查找,如果 obj.prototype 或者 __ prop__ 里还没有就回持续往上查找,直到最顶层都还没有就回返回 undefined 这样一个链式构造就是原型链,原型链最顶层是 null

__prop__是各浏览器厂商实现的

能够在原型链上定义方法

person.prototype.eat = function () {...}

扭转原型:prototype 指向另一个 prototype 即可

JS 实现继承

参考(command + 点击)

  • 1. 原型链继承
  • 2. 结构继承:
  • 3. 实例继承
  • 4. 拷贝继承:
  • 5. 组合继承:
  • 6. 寄生组合继承:
  • 7.class – extends – – ES6

JS 数组相干办法

扭转原数组

Array.push(),向数组的开端增加一个或多个元素,并返回新的数组长度。原数组扭转。

Array.pop(),删除并返回数组的最初一个元素,若该数组为空,则返回 undefined。原数组扭转。

Array.unshift(),向数组的结尾增加一个或多个元素,并返回新的数组长度。原数组扭转。

Array.shift(),删除数组的第一项,并返回第一个元素的值。若该数组为空,则返回 undefined。原数组扭转。

Array.concat(arr1,arr2…),合并两个或多个数组,生成一个新的数组。原数组不变。

Array.join(),将数组的每一项用指定字符连贯造成一个字符串。默认连贯字符为“,”逗号。

Array.reverse(),将数组倒序。原数组扭转。

Array.sort(),对数组元素进行排序。依照字符串 UniCode 码排序,原数组扭转。

Array.splice(index,howmany,arr1,arr2…)删除元素并增加元素,从 index 地位开始删除 howmany 个元素,并将 arr1、arr2… 数据从 index 地位顺次插入。howmany 为 0 时,则不删除元素。原数组扭转。

Array.splice()从 start 开始,end 之前完结,不到 end;如果不给 end 值,从 start 开始到数组完结。start 能够给负值,- 1 示意数组最初地位,- 2 示意倒数第二个,以此类推,顾前不顾后。

不扭转原数组

Array.map(function),原数组的每一项执行函数后,返回一个新的数组。原数组不变。

Array.forEach(function),用于调用数组的每个元素,并将元素传递给回调函数。原数组不变

Array.filter(function),过滤数组中,符合条件的元素并返回一个新的数组。

Array.every(function),对数组中的每一项进行判断,若都合乎则返回 true,否则返回 false。例如:1 是否都小于[1,2,3,4]

Array.some(function),对数组中的每一项进行判断,若都不合乎则返回 false,否则返回 true。例如:1 是否存在于 [1,2,3,4,5] 数组中

Array.reduce(function),reduce() 办法接管一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。

数组去重

  1. 检测以后值在原数组中第一次呈现的地位在与以后下标做比照[皱眉]
let datas = [1, 4, 2, 5, 4, 2, 6, 4, 7, 4, 3, 6, 3, 7, 8, 32, 564, 23, 45, 234, 65, 34, 6, 34, 5, 23]
// 检测以后值在原数组中第一次呈现的地位在与以后下标做比照[皱眉]
datas = datas.filter((item, index, arr) => {
    /**
     * indexOf(item,start)
     * item 必须。查找的元素。* start 规定在数组中开始检索的地位
     */
    return arr.indexOf(item, 0) === index
})
console.log(datas);
  1. new Set() 配合 Array.from
Array.from(new Set([...]))
           
  1. 循环判断法
let newArr = []
datas.forEach((item, index, arr) => {if (!newArr.includes(item)) newArr.push(item)
})
console.log(newArr);
  1. set 加扩大运算符[…]
datas = [...new Set(datas)]
console.log(datas);
  1. Map 对象加 filter
/**
*Map 对象是 ES6 提供的一个新的数据结构,* 其中 has 的方法是返回一个布尔值,示意某个值是否存在以后的 Mp 对象之中,*set 的方法是给 Map 对象设置 key/value。*/
function unique(arr) {let map = new Map()
    return arr.filter(item => !map.has(item) && map.set(item, 1))
}
console.log(unique(datas));

Map 和 Set

参考 command + 单击

本地存储

  1. cookie

    cookie 用于保留网站的一些登录信息,验证密钥等,最大可保留 4k 数据,调用 api 的时候会主动携带 cookie 在 HTTP 申请头中,如果应用 cookie 保留过多数据会带来性能问题

  2. localStorage

    用于短暂保留整个网站的数据,保留的数据没有过期工夫,直到手动去除,个别 5M 左右

  3. sessionStorage

    用于长期保留同一窗口 (或标签页) 的数据,在敞开窗口或标签页之后将会删除这些数据,个别 5M 左右

操作 localStorage 和 sessionStorage

  • 通过 setItem(key, value) 设置数据,
  • 通过 getItem(key) 获取数据,
  • 通过 removeItem(key) 移除数据
  • 通过 clear() 革除所有数据

JS 浏览器缓存 — 强缓存与协商缓存

强缓存:不会向服务器发送申请,间接从缓存中读取资源,能够设置两种 HTTP Header 来实现:Expires、Cache-Control

Expires

  • 缓存过期工夫用来指定资源的过期工夫,是服务器端的具体的工夫点,联合 last-modified 来应用
  • 是 HTTP/1 的产物,受限于本地工夫,如果本地工夫批改可能会造成缓存生效

Cache-Control

  • 能够在申请头或响应头中来设置,多个指令配合应用达到多个目标
  • 是 HTTP/1.1 的产物,如果和 Expires 同时存在,那么它的优先级要高,所以 Expires 的存在成为了一种兼容性的写法

协商缓存

  • 强缓存的根据来自于缓存是否过期,而不关怀服务端文件是否曾经更新,这可能会导致加载的文件不是服务端最新的内容,此时咱们就须要用到协商缓存
  • 协商缓存就是强制缓存生效后,浏览器携带缓存标识向服务器发送申请,由服务器依据缓存标识决定是否应用缓存的过程,次要分两种状况

    • 协商缓存失效返回 304 和 Not Modified
    • 协商缓存生效返回 200 和申请的后果
  • 协商缓存能够通过设置两种 HTTP Header 来实现:Last-Modified 和 ETag

参考 command + 点击

VUE

个性

渐进式,组件化开发,数据响应式,双向数据绑定,数据驱动视图

vue 指令

v-if v-else v-else-if v-show v-for v-bind v-ones v-on v-html v-text v-model

vue 修饰符

  1. lazy,在默认状况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步。你能够增加 lazy 修饰符,相当于在 onchange 事件触发更新。
  2. trim,过滤首尾空格
  3. number 将值转换成 number 类型

事件修饰符:

  1. stop,阻止事件冒泡
  2. prevent,阻止事件默认行为
  3. self,点击事件绑定的自身才会触发事件
  4. once 一次性事件
  5. native 转化为原生事件

v-if 和 v-show 的区别

if 和 show 都是管制 dom 的显示与暗藏,不同的在于 if 是间接删除 dom show 是通过 cssdisplay: block / none;管制 domd 的显示暗藏,不会删除 dom

须要频繁切换的场景下倡议应用 show,如果是简略的 dom 构造显示暗藏两者都能够

为什么 vue 中 data 必须是一个函数

为了保障组件的独立性和可复用性:data 是一个函数,组件实例化的时候这个函数将会被调用,返回一个对象,计算机会给这个对象调配一个内存地址,你实例化几次,就调配几个内存地址,他们的地址都不一样,所以每个组件中的数据不会互相烦扰,扭转其中一个组件的状态,其它组件不变。

key 的作用

当 vue 在进行新旧虚构 dom diff 比照的时候,patch 函数会通过元素的 tag 和 key 来判断是不是同一个元素,如果不设置 key 就默认为 undefined, 比照的时候两个元素就会认为是同一个,导致视图没更新,例如两个 input 互相切换,没有 key 切换的时候就回保留上一个 input 元素的 value 值,还有一种状况就是列表渲染的时候,当没有设置 key 的时候,列表产生扭转时所有列表都会更新,设置 key 之后只会更新对应的列表项

vue 中 computed 和 watch 的区别

computed

  1. 反对缓存,只有依赖数据产生扭转,才会从新进行计算
  2. 不反对异步,当 computed 内有异步操作时有效,无奈监听数据的变动
  3. computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于 data 中申明过的数据通过计算失去的
  4. 如果一个属性是由其余属性计算而来的,这个属性依赖其余属性,是一个多对一或者一对一,个别用 computed
  5. 如果 computed 属性属性值是函数,那么默认会走 get 办法;函数的返回值就是属性的属性值;在 computed 中的,属性都有一个 get 和一个 set 办法,当数据变动时,调用 set 办法。

watch

  1. 不反对缓存,数据变,间接会触发相应的操作;
  2. watch 反对异步;
  3. 监听的函数接管两个参数,第一个参数是最新的值;第二个参数是输出之前的值;
  4. 当一个属性发生变化时,须要执行对应的操作;一对多;

computed 和 methods 的区别

  1. computed 只能作为属性应用,methods 只能作为办法调用
  2. computed 具备 getter 和 setter,因而能够赋值,而 methods 不能
  3. computed 无奈承受多个参数,而 methods 能够
  4. computed 具备缓存,执行过一次之后第二次就间接应用缓存的后果而不回在此执行 computed,而 methods 没有缓存

进阶:

vue 对 methods 的解决比较简单,只须要遍历 methods 配置中的每个属性,将其对应的函数应用 bind 绑定以后组件实例后复制其援用到组件实例中即可,这样就能够应用 this 调用

Vue 它会遍历 computed 配置中的所有属性,为每一个属性创立一个 Watcher 对象,并传入一个函数,该函数的实质其实就是 computed 配置中的 getter,这样一来,getter 运行过程中就会收集依赖,然而这个 watcher 不回立刻执行,只有在该 computed 属性被应用的时候才会执行,

vue 组件通信

父子之间通信:

prop,event,style 和 class,natvie 修饰符,sync 修饰符,$listeners,v-model,$parent 和 $children,$slots 和 $scopedSlots,ref

跨组件通信:

vuex,router,eventBus,store 模式,Provide 和 Inject

参考 (command + 单击)

vue 数据响应式(双向数据绑定)原理

vue 的数据响应只有通过 4 个核心部件来实现的,别离是:

  1. Observer
  2. Dep
  3. Watcher
  4. Scheduler

Observer 的作用很简略,次要是通过 Object.defineProperty 将数据包装成一个带有 getter/setter 的非凡属性,读取数据的时候通过 getter 办法,写入数据的时候通过 setter 办法

其中对对象和数组的解决有所不同,对象是间接通过 Observer 去包装,而数组则是重写了可能扭转数组的一些办法,例如push, pop, shift, unshift, splice, sort, reverse,而后在通过 observeArray 办法去遍历数组里的数据,是数据具备响应式

Dep 次要是收集依赖和告诉依赖更新,当数据被应用的时候就回调用 getter 办法,get 外面会通过 dep 实例调用 dep.depend()办法,收集依赖;当数据被扭转的时候就回告诉依赖更新,set 外面通过 dep 实况调用 dep.notify()办法告诉所有订阅者依赖更新。

当某个函数在执行的过程中,应用到了响应式数据时,vue 就会为响应式数据创立一个 watcher 实例,当数据产生扭转时,vue 不间接告诉相干依赖更新,而是告诉依赖对应的 watcher 实例去执行。

watcher 实例不间接更新视图,而是交给 scheduler 调度器,scheduler保护一个事件队列通过 nextTick 执行事件,从而更新视图。

参考 (command + 单击)

v-model 的原理

v-model 能够作用到表单元素或者自定义组件上,

作用在表单元素上有两种状况,

  1. 一般表单元素,例如 input 时,生成一个 value 属性和 input 办法
  2. 单选框或者复选框元素,生成一个 checked 属性和一个 change 办法

作用在自定义组件时默认生成一个 value 属性和一个 input 办法,也能够通过配置组件外部的 model 来扭转默认的属性和办法

// Comp
const Comp = {
  model: {
    prop: "number", // 默认为 value
    event: "change" // 默认为 input
  }
  // ...
}

参考 (command + 单击

vue 生命周期

分为五个阶段,初始化阶段(beforeCreate,created),模版编译阶段(生成 render 函数),挂载阶段(beforemunt,munted),更新阶段(beforeUpdate,update),销毁阶段(before Destroy,destroyed)

初始化阶:段次要设置一些所有属性到 vue 实例中,并解决 computed,methods,data,provide,inject 属性,应用代理模式将这些属性挂载到 vue 实例中

编译阶段:次要将模版编译成 render 函数

挂载阶段:次要将 render 函数运行取得的虚构 DOM 依照每一个节点创立对应的 elm 属性,即实在 DOM,在这一过程中,会收集所有动态数据的依赖

更新阶段:动态数据产生扭转后之前收集的依赖 Watcher 会被从新运行,促发一个叫做 updateCompontent 的函数,该函数会呈现执行 render 函数取得新的 vnode,并把新的 vnode 作为参数过_update 函数,在执行 update 函数的过程中,会触发 patch 函数比照新旧两颗 dom 树

销毁阶段:组件来到或者所销毁的时候,会调用组件的 $destroy 办法删除组件,该办法会先后调用 beforeDestroy 和 destroy 办法,移除本身所有的依赖和事件监听,彻底销毁组件实例

参考(command + 单机)

vue 中 mixin 用法

mixin 能够全局混入,也能够组件混入,通过 mixin 混入的生命周期会和组件的生命周期进行合并,抵触的办法以组件里的为主,执行程序:

  1. 对于 created,mounted 等生命周期函数 mixin 文件中的代码先执行,组件中的后执行
  2. 对于 data 中定义的字段,组件中定义组件笼罩 mixin 中同名字段
  3. 对于 method 中的同名办法,组件内的同名办法笼罩 mixin 中的办法

vue 自定义指令

  1. bind 只调用一次,指令第一次绑定到元素时候调用,用这个钩子能够定义一个绑定时执行一次的初始化动作。
  2. inserted: 被绑定的元素插入父节点的时候调用(父节点存在即可调用,不用存在 document 中)
  3. update: 被绑定于元素所在模板更新时调用,而且无论绑定值是否有变动,通过比拟更新前后的绑定值,疏忽不必要的模板更新
  4. componentUpdate : 被绑定的元素所在模板实现一次更新更新周期的时候调用
  5. unbind: 只调用一次,指令与元素解绑的时候调用
Vue.directive("hello",{bind:function(el,bingind,vnode){
            // 只调用一次,指令第一次绑定到元素时候调用,// 用这个钩子能够定义一个绑定时执行一次的初始化动作。el.style["color"] = bingind.value;
            console.log("1-bind");
        },
        inserted:function(){// 被绑定的元素插入父节点的时候调用(父节点存在即可调用,不用存在 document 中)
            console.log("2-inserted");
        },
        update:function(){
            // 被绑定于元素所在模板更新时调用,而且无论绑定值是否有变动
            // 通过比拟更新前后的绑定值,疏忽不必要的模板更新
            console.log("3-update");
        },
        componentUpdated:function(){
            // 被绑定元素所在模板实现一次更新周期时调用
            console.log('4 - componentUpdated');
        },
        unbind:function(){
            // 只调用一次,指令与元素解绑时调用。console.log('5 - unbind');
        }
    })

vue 相干优化

  1. 列表应用 Key
  2. 静态数据应用对象解冻,比方长列表,列表数据不须要增删改的状况下能够应用 Object.freeze 解冻对象,被解冻的对象不回被响应化
  3. 应用函数式组件,在不须要组件实例的组件中应用函数式组件

    Vue.component('my-component', {
      functional: true,
      // Props 是可选的
      props: {// ...},
      // 为了补救短少的实例
      // 提供第二个参数作为上下文
      render: function (createElement, context) {// ...}
    })
  4. 应用计算属性,如果模板中某个数据会应用屡次,并且该数据是通过计算失去的,应用计算属性以缓存它们
  5. 应用非实时绑定的表单

    当应用 v-model 绑定一个表单项时,当用户扭转表单项的状态时,也会随之扭转数据,从而导致 vue 产生重渲染(rerender),这会带来一些性能的开销。

    特地是当用户扭转表单项时,页面有一些动画正在进行中,因为 JS 执行线程和浏览器渲染线程是互斥的,最终会导致动画呈现卡顿。

    咱们能够通过应用 lazy 或不应用 v-model 的形式解决该问题,但要留神,这样可能会导致在某一个时间段内数据和表单项的值是不统一的。

  6. 在频繁切换显示暗藏的时候应用 v -show 代替 v -if

    对于频繁切换显示状态的元素,应用 v -show 能够保障虚构 dom 树的稳固,防止频繁的新增和删除元素,特地是对于那些外部蕴含大量 dom 元素的节点,这一点极其重要

    关键字:频繁切换显示状态、外部蕴含大量 dom 元素

  7. 应用提早装载(defer)

    首页白屏工夫次要受到两个因素的影响:

    • 打包体积过大

      巨型包须要耗费大量的传输工夫,导致 JS 传输实现前页面只有一个<div>,没有可显示的内容

    • 须要立刻渲染的内容太多

      JS 传输实现后,浏览器开始执行 JS 结构页面。

      但可能一开始要渲染的组件太多,不仅 JS 执行的工夫很长,而且执行完后浏览器要渲染的元素过多,从而导致页面白屏

    打包体积过大须要自行优化打包体积,本节不予探讨

    本节仅探讨渲染内容太多的问题。

    一个可行的方法就是 提早装载组件,让组件依照指定的先后顺序顺次一个一个渲染进去

    提早装载是一个思路,实质上就是利用 requestAnimationFrame 事件分批渲染内容,它的具体实现多种多样

    // mixins
    export default function(maxFrameCount) {
      return {data() {
          return {frameCount: 0,};
        },
        mounted() {const refreshFrameCount = () => {requestAnimationFrame(() => {
              this.frameCount++;
              if (this.frameCount < maxFrameCount) {refreshFrameCount();
              }
            });
          };
          refreshFrameCount();},
        methods: {defer(showInFrameCount) {return this.frameCount >= showInFrameCount;},
        },
      };
    }
    
  1. 应用 Keep- alive 缓存组件
  2. 长列表优化,当有大量列表须要展现的时候,不须要一次性将所有列表渲染进去,只须要渲染可视区域及可视区域以下的一部分列表,并为这些曾经渲染的列表设置相对定位,让后通过计算滚动地位来不停更新开始区域的列表即可,不须要渲染所有的数据列表(插件:VueVirtualScroller)

keep-alive

keep-alive 组件是 vue 的内置组件,用于缓存外部组件实例。这样做的目标在于,keep-alive 外部的组件切回时,不必从新创立组件实例,而间接应用缓存中的实例,一方面可能防止创立组件带来的开销,另一方面能够保留组件的状态。

keep-alive 具备 include 和 exclude 属性,通过它们能够管制哪些组件进入缓存。另外它还提供了 max 属性,通过它能够设置最大缓存数,当缓存的实例超过该数时,vue 会移除最久没有应用的组件缓存。

受 keep-alive 的影响,其外部所有嵌套的组件都具备两个生命周期钩子函数,别离是 activateddeactivated,它们别离在组件激活和失活时触发。第一次 activated 触发是在 mounted 之后

vue 过渡和动画

应用内置组件 Transition 实现动画

Transition组件会监控 slot惟一 根元素的呈现和隐没,并会在其呈现和隐没时利用过渡成果

具体的监听内容是:

  • 它会对新旧两个虚构节点进行比照,如果旧节点被销毁,则利用隐没成果,如果新节点是新增的,则利用进入成果
  • 如果不是上述情况,则它会比照新旧节点,察看其 v-show 是否变动,true->false利用隐没成果,false->true利用进入成果

TransitionGroup组件能够监听列表的变动它会对列表的新增元素利用 进入成果 ,删除元素利用 隐没成果 ,对被挪动的元素利用v-move 款式

被挪动的元素之所以可能实现过渡成果,是因为 TransisionGroup 外部应用了 Flip 过渡计划

vue 组件封装

次要蕴含三局部:prop、event、slot

  • props 示意组件接管的参数,最好用对象的写法,这样能够针对每个属性设置类型、默认值或自定义校验属性的值,此外还能够通过 type、validator 等形式对输出进行验证
  • slot 能够给组件动静插入一些内容或组件,是实现高阶组件的重要途径;当须要多个插槽时,能够应用具名 slot
  • event 是子组件向父组件传递音讯的重要途径

参考 command + 单击

VUE3

vue3 相比拟 vue2 的一些变动

  1. vue3 去掉了 vue 构造函数,通过导出一个 createApp 的办法来创立一个 vue 我的项目,
  2. 新增了组合式 Api,这样同一个性能的所有业务代码都能够写到一起而不用扩散到组件的各个模块中,
  3. 对于响应式数据的实现形式不同,放弃了 Object.defineProperty 的实现形式,而是应用 Proxy,
  4. v-if 的优先级当初高于 v-for
  5. v-model 的实现形式有所不同

    当对自定义组件应用 v-model 指令时,绑定的属性名由原来的 value 变为 modelValue,事件名由原来的input 变为update:modelValue

    <!-- vue2 -->
    <ChildComponent :value="pageTitle" @input="pageTitle = $event" />
    <!-- 简写为 -->
    <ChildComponent v-model="pageTitle" />
    
    <!-- vue3 -->
    <ChildComponent
      :modelValue="pageTitle"
      @update:modelValue="pageTitle = $event"
    />
    <!-- 简写为 -->
    <ChildComponent v-model="pageTitle" />

    去掉了 .sync 修饰符,它本来的性能由 v-model 的参数代替

    <!-- vue2 -->
    <ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
    <!-- 简写为 -->
    <ChildComponent :title.sync="pageTitle" />
    
    <!-- vue3 -->
    <ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
    <!-- 简写为 -->
    <ChildComponent v-model:title="pageTitle" />
  6. 组件的 model 配置被移除
  7. 容许自定义 v-model 修饰符

    <Compon v-model.cap="data1" v-model:text="data2" />

为什么 vue3 中去掉了 vue 构造函数?

vue2 的全局构造函数带来了诸多问题:

  1. 调用构造函数的静态方法会对所有 vue 利用失效,不利于隔离不同利用
  2. vue2 的构造函数集成了太多功能,不利于 tree shaking,vue3 把这些性能应用一般函数导出,可能充分利用 tree shaking 优化打包体积
  3. vue2 没有把组件实例和 vue 利用两个概念辨别开,在 vue2 中,通过 new Vue 创立的对象,既是一个 vue 利用,同时又是一个非凡的 vue 组件。vue3 中,把两个概念区别开来,通过 createApp 创立的对象,是一个 vue 利用,它外部提供的办法是针对整个利用的,而不再是一个非凡的组件。

vue3 数据响应式的了解

vue3 不再应用 Object.defineProperty 的形式定义实现数据响应式,而是应用 Proxy。
除了 Proxy 自身效率比 Object.defineProperty 更高之外,因为不用递归遍历所有属性,而是间接失去一个 Proxy。所以在 vue3 中,对数据的拜访是动静的,当拜访某个属性的时候,再动静的获取和设置,这就极大的晋升了在组件初始阶段的效率。
同时,因为 Proxy 能够监控到成员的新增和删除,因而,在 vue3 中新增成员、删除成员、索引拜访等均能够触发从新渲染,而这些在 vue2 中是难以做到的。

vue3 中如何定义响应式数据(reactivity api)

API 传入 返回 备注
reactive plain-object 对象代理 深度代理对象中的所有成员
readonly plain-object or proxy 对象代理 只能读取代理对象中的成员,不可批改
ref any {value: ...} 对 value 的拜访是响应式的
如果给 value 的值是一个对象,
则会通过 reactive 函数进行代理
如果曾经是代理,则间接应用代理
computed function {value: ...} 当读取 value 值时,
依据状况 决定是否要运行函数

利用:

  • 如果想要让一个对象变为响应式数据,能够应用 reactiveref
  • 如果想要让一个对象的所有属性只读,应用readonly
  • 如果想要让一个非对象数据变为响应式数据,应用ref
  • 如果想要依据已知的响应式数据失去一个新的响应式数据,应用computed

判断:

API 含意
isProxy 判断某个数据是否是由 reactivereadonly
isReactive 判断某个数据是否是通过 reactive 创立的
具体:https://v3.vuejs.org/api/basi…
isReadonly 判断某个数据是否是通过 readonly 创立的
isRef 判断某个数据是否是一个 ref 对象

composition api 相比于 option api 有哪些劣势?

从两个方面答复:

  1. 为了更好的逻辑复用和代码组织
  2. 更好的类型推导

有了 composition api,配合 reactivity api,能够在组件外部进行更加细粒度的管制,使得组件中不同的性能高度聚合,晋升了代码的可维护性。对于不同组件的雷同性能,也可能更好的复用。
相比于 option api,composition api 中没有了指向奇怪的 this,所有的 api 变得更加函数式,这有利于和类型推断零碎比方 TS 深度配合。

setup

// component
export default {setup(props, context){
    // 该函数在组件属性被赋值后立刻执行,早于所有生命周期钩子函数
    // props 是一个对象,蕴含了所有的组件属性值
    // context 是一个对象,提供了组件所需的上下文信息
  }
}

context 对象的成员

成员 类型 阐明
attrs 对象 vue2this.$attrs
slots 对象 vue2this.$slots
emit 办法 vue2this.$emit

生命周期函数

vue2 option api vue3 option api vue 3 composition api
beforeCreate beforeCreate 不再须要,代码可间接置于 setup 中
created created 不再须要,代码可间接置于 setup 中
beforeMount beforeMount onBeforeMount
mounted mounted onMounted
beforeUpdate beforeUpdate onBeforeUpdate
updated updated onUpdated
beforeDestroy == 改 == beforeUnmount onBeforeUnmount
destroyed == 改 ==unmounted onUnmounted
errorCaptured errorCaptured onErrorCaptured
== 新 ==renderTracked onRenderTracked
== 新 ==renderTriggered onRenderTriggered

新增钩子函数阐明:

钩子函数 参数 执行机会
renderTracked DebuggerEvent 渲染 vdom 收集到的每一次依赖时
renderTriggered DebuggerEvent 某个依赖变动导致组件从新渲染时

DebuggerEvent:

  • target: 跟踪或触发渲染的对象
  • key: 跟踪或触发渲染的属性
  • type: 跟踪或触发渲染的形式

VUEX

vuex 是 vue 的数据状态管理器,外部别离为:

  1. state 数据仓库模块,
  2. mutations 模块,用来扭转 state 的状态,同步执行,
  3. actions 模块,提交一个 mutations 办法扭转 state 状态,异步执行
  4. getter 模块,能够对 state 进行计算操作,相当于 state 的计算属性
  5. modules 模块,能够让 vuex 分模块治理,让每一个模块领有独立的 state,mutations,action,getter 模块,不便数据状态的治理以及数据状态变动的追踪

VUEX 数据状态长久化

将 state 仓库的数据备份到 localStorage 中,或者应用相干插件,例如:persistedstate

VUEX 的 getter 个性

  1. getter 能够对 state 进行计算操作,相当于 state 的计算属性
  2. 便于在组件之间复用 getter 计算属性

VUEX 的 mutations 和 action 的异同

  1. action 相似于 mutations,不同之处在于 action 提交的是 mutations,而不是间接扭转 state 的状态
  2. mutations 是同步执行,action 是一步执行

vue – Router 路由

router-link

用于路由跳转,通过 to 指定跳转门路,默认状况下 router-link 会被渲染成一个 a 标签,能够通过指定 tag 扭转最终渲染的标签,active-class 能够指定被激活的款式。

router-view

路由的进口,跳转的组件在 router-view 里渲染

路由重定向

通过在路由对象里配置 redirect 实现重定向

路由模式

  1. hash 模式,兼容所有浏览器,地址栏会带有 #哈希值
  2. history 模式,只兼容之处 HTML5 history Api 的浏览器,地址栏不会带有 #哈希值
  3. abstract 模式,反对所有 js 运行环境,如 node 环境,如果不在浏览器环境里运行,路由会主动切换到该模式

路由守卫

  1. 全局钩子:beforeEach、afterEach、beforeResolve
  2. 单个路由外面的钩子:beforeEnter
  3. 组件内路由钩子函数:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
// 全局前置路由钩子函数
beforeEach(to,from,next){next()
}

// 全局后置路由钩子函数
afterEach(to,from){}

// 全局解析守卫 这和 beforeEach 相似
beforeResolve(){}

// 路由独享守卫
const routes = [
  {
    path: '/users/:id',
    component: UserDetails,
    beforeEnter: (to, from) => {
      // reject the navigation
      return false
    },
  },
]

// 组件内的守卫
const UserDetails = {
  template: `...`,
  beforeRouteEnter(to, from) {
    // 在渲染该组件的对应路由被验证前调用
    // 不能获取组件实例 `this`!// 因为当守卫执行时,组件实例还没被创立!},
  beforeRouteUpdate(to, from) {
    // 在以后路由扭转,然而该组件被复用时调用
    // 举例来说,对于一个带有动静参数的门路 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,// 因为会渲染同样的 `UserDetails` 组件,因而组件实例会被复用。而这个钩子就会在这个状况下被调用。// 因为在这种状况产生的时候,组件曾经挂载好了,导航守卫能够拜访组件实例 `this`
  },
  beforeRouteLeave(to, from) {
    // 在导航来到渲染该组件的对应路由时调用
    // 与 `beforeRouteUpdate` 一样,它能够拜访组件实例 `this`
  },
}

残缺的路由钩子触发流程

  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫(2.2+)。
  5. 在路由配置里调用 beforeEnter
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve 守卫(2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创立好的组件实例会作为回调函数的参数传入。

路由跳转

在 Vue 实例中,能够通过 $router 拜访路由实例。能够调用 this.$router.push导航到不同的页面

// 字符串门路
router.push('/users/eduardo')

// 带有门路的对象
router.push({path: '/users/eduardo'})

// 命名的路由,并加上参数,让路由建设 url
router.push({name: 'user', params: { username: 'eduardo'} })

// 带查问参数,后果是 /register?plan=private
router.push({path: '/register', query: { plan: 'private'} })

// 带 hash,后果是 /about#team
router.push({path: '/about', hash: '#team'})

// 向前挪动一条记录,与 router.forward() 雷同
router.go(1)

记录滚动地位

const router = createRouter({history: createWebHashHistory(),
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    // return 冀望滚动到哪个的地位
    return {
        top:0,
      left:0
    }
  }
})

axios

特点

  1. Axios 是一个基于 promise 的 HTTP 库,反对 promise 所有的 API
  2. 它能够拦挡申请和响应
  3. 它能够转换申请数据和响应数据,并对响应回来的内容主动转换成 JSON 类型的数据
  4. 安全性更高,客户端反对进攻 XSRF

axios 相干的配置属性

  1. ‘url’是用于申请的服务器 url
  2. ‘method’是创立申请时应用的办法,默认是 get,
  3. ‘baseURL’将主动加在 url 后面,除非 url 是一个相对 URL。
  4. ’transformRequest‘容许在向服务器发送前,批改申请数据,只能用在’put\post\patch’这几个申请办法。
  5. ‘headers’自定义申请头。
  6. ‘params’是行将与申请一起发送的 url 参数,必须是一个无格局对象或 URLSearchParams 对象
  7. ‘auth’示意被告 i 应用 HTTP 根底验证,并提供票据,这将设置一个 Authorization 头,覆写掉现有的热比一使
  8. headers 设置的自定义 Authorization 头
  9. ‘proxy’定义代理服务器的主机名称和端口

axios 申请拦截器与响应拦截器

// 增加申请拦截器
axios.interceptors.request.use(function (config) {
    // 在发送申请之前做些什么
    return config;
  }, function (error) {
    // 对申请谬误做些什么
    return Promise.reject(error);
  });


// 增加响应拦截器
axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response;
  }, function (error) {
    // 对响应谬误做点什么
    return Promise.reject(error);
  });
退出移动版