乐趣区

关于javascript:2022秋招前端面试题六附答案

代码输入后果

console.log(1);

setTimeout(() => {console.log(2);
  Promise.resolve().then(() => {console.log(3)
  });
});

new Promise((resolve, reject) => {console.log(4)
  resolve(5)
}).then((data) => {console.log(data);
})

setTimeout(() => {console.log(6);
})

console.log(7);
复制代码

代码输入后果如下:

1
4
7
5
2
3
6
复制代码

代码执行过程如下:

  1. 首先执行 scrip 代码,打印出 1;
  2. 遇到第一个定时器 setTimeout,将其退出到宏工作队列;
  3. 遇到 Promise,执行外面的同步代码,打印出 4,遇到 resolve,将其退出到微工作队列;
  4. 遇到第二个定时器 setTimeout,将其退出到红工作队列;
  5. 执行 script 代码,打印出 7,至此第一轮执行实现;
  6. 指定微工作队列中的代码,打印出 resolve 的后果:5;
  7. 执行宏工作中的第一个定时器 setTimeout,首先打印出 2,而后遇到 Promise.resolve().then(),将其退出到微工作队列;
  8. 执行完这个宏工作,就开始执行微工作队列,打印出 3;
  9. 继续执行宏工作队列中的第二个定时器,打印出 6。

事件流

事件流是网页元素接管事件的程序,”DOM2 级事件 ” 规定的事件流包含三个阶段:事件捕捉阶段、处于指标阶段、事件冒泡阶段。
首先产生的事件捕捉,为截获事件提供机会。而后是理论的指标承受事件。最初一个阶段是工夫冒泡阶段,能够在这个阶段对事件做出响应。
尽管捕捉阶段在标准中规定不容许响应事件,然而实际上还是会执行,所以有两次机会获取到指标对象。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title> 事件冒泡 </title>
</head>
<body>
    <div>
        <p id="parEle"> 我是父元素    <span id="sonEle"> 我是子元素 </span></p>
    </div>
</body>
</html>
<script type="text/javascript">
var sonEle = document.getElementById('sonEle');
var parEle = document.getElementById('parEle');parEle.addEventListener('click', function () {alert('父级 冒泡');}, false);parEle.addEventListener('click', function () {alert('父级 捕捉');}, true);sonEle.addEventListener('click', function () {alert('子级冒泡');}, false);sonEle.addEventListener('click', function () {alert('子级捕捉');}, true);

</script>
复制代码

当容器元素及嵌套元素,即在 捕捉阶段 又在 冒泡阶段 调用事件处理程序时:事件按 DOM 事件流的程序 执行事件处理程序:

  • 父级捕捉
  • 子级捕捉
  • 子级冒泡
  • 父级冒泡

且当事件处于指标阶段时,事件调用程序决定于绑定事件的 书写程序,按下面的例子为,先调用冒泡阶段的事件处理程序,再调用捕捉阶段的事件处理程序。顺次 alert 出“子集冒泡”,“子集捕捉”。

为什么须要浏览器缓存?

对于浏览器的缓存,次要针对的是前端的动态资源,最好的成果就是,在发动申请之后,拉取相应的动态资源,并保留在本地。如果服务器的动态资源没有更新,那么在下次申请的时候,就间接从本地读取即可,如果服务器的动态资源曾经更新,那么咱们再次申请的时候,就到服务器拉取新的资源,并保留在本地。这样就大大的缩小了申请的次数,进步了网站的性能。这就要用到浏览器的缓存策略了。

所谓的 浏览器缓存 指的是浏览器将用户申请过的动态资源,存储到电脑本地磁盘中,当浏览器再次拜访时,就能够间接从本地加载,不须要再去服务端申请了。

应用浏览器缓存,有以下长处:

  • 缩小了服务器的累赘,进步了网站的性能
  • 放慢了客户端网页的加载速度
  • 缩小了多余网络数据传输

事件触发的过程是怎么的

事件触发有三个阶段:

  • window 往事件触发处流传,遇到注册的捕捉事件会触发
  • 流传到事件触发处时触发注册的事件
  • 从事件触发处往 window 流传,遇到注册的冒泡事件会触发

事件触发一般来说会依照下面的程序进行,然而也有特例,如果给一个 body 中的子节点同时注册冒泡和捕捉事件,事件触发会依照注册的程序执行。

// 以下会先打印冒泡而后是捕捉
node.addEventListener(
  'click',
  event => {console.log('冒泡')
  },
  false
)
node.addEventListener(
  'click',
  event => {console.log('捕捉')
  },
  true
)
复制代码

通常应用 addEventListener 注册事件,该函数的第三个参数能够是布尔值,也能够是对象。对于布尔值 useCapture 参数来说,该参数默认值为 falseuseCapture 决定了注册的事件是捕捉事件还是冒泡事件。对于对象参数来说,能够应用以下几个属性:

  • capture:布尔值,和 useCapture 作用一样
  • once:布尔值,值为 true 示意该回调只会调用一次,调用后会移除监听
  • passive:布尔值,示意永远不会调用 preventDefault

一般来说,如果只心愿事件只触发在指标上,这时候能够应用 stopPropagation 来阻止事件的进一步流传。通常认为 stopPropagation 是用来阻止事件冒泡的,其实该函数也能够阻止捕捉事件。

stopImmediatePropagation 同样也能实现阻止事件,然而还能阻止该事件指标执行别的注册事件。

node.addEventListener(
  'click',
  event => {event.stopImmediatePropagation()
    console.log('冒泡')
  },
  false
)
// 点击 node 只会执行下面的函数,该函数不会执行
node.addEventListener(
  'click',
  event => {console.log('捕捉')
  },
  true
)
复制代码

如果一个构造函数,bind 了一个对象,用这个构造函数创立出的实例会继承这个对象的属性吗?为什么?

不会继承,因为依据 this 绑定四大规定,new 绑定的优先级高于 bind 显示绑定,通过 new 进行结构函数调用时,会创立一个新对象,这个新对象会代替 bind 的对象绑定,作为此函数的 this,并且在此函数没有返回对象的状况下,返回这个新建的对象

浏览器本地存储形式及应用场景

(1)Cookie

Cookie 是最早被提出来的本地存储形式,在此之前,服务端是无奈判断网络中的两个申请是否是同一用户发动的,为解决这个问题,Cookie 就呈现了。Cookie 的大小只有 4kb,它是一种纯文本文件,每次发动 HTTP 申请都会携带 Cookie。

Cookie 的个性:

  • Cookie 一旦创立胜利,名称就无奈批改
  • Cookie 是无奈跨域名的,也就是说 a 域名和 b 域名下的 cookie 是无奈共享的,这也是由 Cookie 的隐衷安全性决定的,这样就可能阻止非法获取其余网站的 Cookie
  • 每个域名下 Cookie 的数量不能超过 20 个,每个 Cookie 的大小不能超过 4kb
  • 有平安问题,如果 Cookie 被拦挡了,那就可取得 session 的所有信息,即便加密也于事无补,无需晓得 cookie 的意义,只有转发 cookie 就能达到目标
  • Cookie 在申请一个新的页面的时候都会被发送过来

如果须要域名之间跨域共享 Cookie,有两种办法:

  1. 应用 Nginx 反向代理
  2. 在一个站点登陆之后,往其余网站写 Cookie。服务端的 Session 存储到一个节点,Cookie 存储 sessionId

Cookie 的应用场景:

  • 最常见的应用场景就是 Cookie 和 session 联合应用,咱们将 sessionId 存储到 Cookie 中,每次发申请都会携带这个 sessionId,这样服务端就晓得是谁发动的申请,从而响应相应的信息。
  • 能够用来统计页面的点击次数

(2)LocalStorage

LocalStorage 是 HTML5 新引入的个性,因为有的时候咱们存储的信息较大,Cookie 就不能满足咱们的需要,这时候 LocalStorage 就派上用场了。

LocalStorage 的长处:

  • 在大小方面,LocalStorage 的大小个别为 5MB,能够贮存更多的信息
  • LocalStorage 是长久贮存,并不会随着页面的敞开而隐没,除非被动清理,不然会永恒存在
  • 仅贮存在本地,不像 Cookie 那样每次 HTTP 申请都会被携带

LocalStorage 的毛病:

  • 存在浏览器兼容问题,IE8 以下版本的浏览器不反对
  • 如果浏览器设置为隐衷模式,那咱们将无奈读取到 LocalStorage
  • LocalStorage 受到同源策略的限度,即端口、协定、主机地址有任何一个不雷同,都不会拜访

LocalStorage 的罕用 API:

// 保留数据到 localStorage
localStorage.setItem('key', 'value');

// 从 localStorage 获取数据
let data = localStorage.getItem('key');

// 从 localStorage 删除保留的数据
localStorage.removeItem('key');

// 从 localStorage 删除所有保留的数据
localStorage.clear();

// 获取某个索引的 Key
localStorage.key(index)
复制代码

LocalStorage 的应用场景:

  • 有些网站有换肤的性能,这时候就能够将换肤的信息存储在本地的 LocalStorage 中,当须要换肤的时候,间接操作 LocalStorage 即可
  • 在网站中的用户浏览信息也会存储在 LocalStorage 中,还有网站的一些不常变动的个人信息等也能够存储在本地的 LocalStorage 中

(3)SessionStorage

SessionStorage 和 LocalStorage 都是在 HTML5 才提出来的存储计划,SessionStorage 次要用于长期保留同一窗口 (或标签页) 的数据,刷新页面时不会删除,敞开窗口或标签页之后将会删除这些数据。

SessionStorage 与 LocalStorage 比照:

  • SessionStorage 和 LocalStorage 都在 本地进行数据存储
  • SessionStorage 也有同源策略的限度,然而 SessionStorage 有一条更加严格的限度,SessionStorage只有在同一浏览器的同一窗口下才可能共享
  • LocalStorage 和 SessionStorage都不能被爬虫爬取

SessionStorage 的罕用 API:

// 保留数据到 sessionStorage
sessionStorage.setItem('key', 'value');

// 从 sessionStorage 获取数据
let data = sessionStorage.getItem('key');

// 从 sessionStorage 删除保留的数据
sessionStorage.removeItem('key');

// 从 sessionStorage 删除所有保留的数据
sessionStorage.clear();

// 获取某个索引的 Key
sessionStorage.key(index)
复制代码

SessionStorage 的应用场景

  • 因为 SessionStorage 具备时效性,所以能够用来存储一些网站的游客登录的信息,还有长期的浏览记录的信息。当敞开网站之后,这些信息也就随之打消了。

实现数组原型办法

forEach

语法:arr.forEach(callback(currentValue [, index [, array]])[, thisArg])

参数:

callback:为数组中每个元素执行的函数,该函数承受 1 - 3 个参数currentValue: 数组中正在解决的以后元素index(可选): 数组中正在解决的以后元素的索引array(可选): forEach() 办法正在操作的数组 thisArg(可选): 当执行回调函数 callback 时,用作 this 的值。

返回值:undefined

Array.prototype.forEach1 = function(callback, thisArg) {if(this == null) {throw new TypeError('this is null or not defined');
    }
    if(typeof callback !== "function") {throw new TypeError(callback + 'is not a function');
    }
    // 创立一个新的 Object 对象。该对象将会包裹 (wrapper) 传入的参数 this(以后数组)。const O = Object(this);
    // O.length >>> 0 无符号右移 0 位
    // 意义:为了保障转换后的值为正整数。// 其实底层做了 2 层转换,第一是非 number 转成 number 类型,第二是将 number 转成 Uint32 类型
    const len = O.length >>> 0;
    let k = 0;
    while(k < len) {if(k in O) {callback.call(thisArg, O[k], k, O);
        }
        k++;
    }
}
复制代码

map

语法:arr.map(callback(currentValue [, index [, array]])[, thisArg])

参数:与 forEach() 办法一样

返回值:一个由原数组每个元素执行回调函数的后果组成的新数组。

Array.prototype.map1 = function(callback, thisArg) {if(this == null) {throw new TypeError('this is null or not defined');
    }
    if(typeof callback !== "function") {throw new TypeError(callback + 'is not a function');
    }
    const O = Object(this); 
    const len = O.length >>> 0;
    let newArr = [];  // 返回的新数组
    let k = 0;
    while(k < len) {if(k in O) {newArr[k] = callback.call(thisArg, O[k], k, O);
        }
        k++;
    }
    return newArr;
}
复制代码

filter

语法:arr.filter(callback(element [, index [, array]])[, thisArg])

参数:

callback: 用来测试数组的每个元素的函数。返回 true 示意该元素通过测试,保留该元素,false 则不保留。它承受以下三个参数:element、index、array,参数的意义与 forEach 一样。

thisArg(可选): 执行 callback 时,用于 this 的值。

返回值:一个新的、由通过测试的元素组成的数组,如果没有任何数组元素通过测试,则返回空数组。

Array.prototype.filter1 = function(callback, thisArg) {if(this == null) {throw new TypeError('this is null or not defined');
    }
    if(typeof callback !== "function") {throw new TypeError(callback + 'is not a function');
    }
    const O = Object(this); 
    const len = O.length >>> 0;
    let newArr = [];  // 返回的新数组
    let k = 0;
    while(k < len) {if(k in O) {if(callback.call(thisArg, O[k], k, O)) {newArr.push(O[k]);
            }
        }
        k++;
    }
    return newArr;
}
复制代码

some

语法:arr.some(callback(element [, index [, array]])[, thisArg])

参数:

callback: 用来测试数组的每个元素的函数。承受以下三个参数:element、index、array,参数的意义与 forEach 一样。

thisArg(可选): 执行 callback 时,用于 this 的值。
返回值:数组中有至多一个元素通过回调函数的测试就会返回 true;所有元素都没有通过回调函数的测试返回值才会为 false

Array.prototype.some1 = function(callback, thisArg) {if(this == null) {throw new TypeError('this is null or not defined');
    }
    if(typeof callback !== "function") {throw new TypeError(callback + 'is not a function');
    }
    const O = Object(this); 
    const len = O.length >>> 0;
    let k = 0;
    while(k < len) {if(k in O) {if(callback.call(thisArg, O[k], k, O)) {return true}
        }
        k++;
    }
    return false;
}
复制代码

reduce

语法:arr.reduce(callback(preVal, curVal[, curIndex [, array]])[, initialValue])

参数:

callback: 一个“reducer”函数,蕴含四个参数:

preVal:上一次调用 callback 时的返回值。在第一次调用时,若指定了初始值 initialValue,其值则为 initialValue,否则为数组索引为 0 的元素 array[0]

curVal:数组中正在解决的元素。在第一次调用时,若指定了初始值 initialValue,其值则为数组索引为 0 的元素 array[0],否则为 array[1]

curIndex(可选):数组中正在解决的元素的索引。若指定了初始值 initialValue,则起始索引号为 0,否则从索引 1 起始。

array(可选):用于遍历的数组。
initialValue(可选): 作为第一次调用 callback 函数时参数 preVal 的值。若指定了初始值 initialValue,则 curVal 则将应用数组第一个元素;否则 preVal 将应用数组第一个元素,而 curVal 将应用数组第二个元素。
返回值:应用“reducer”回调函数遍历整个数组后的后果。

Array.prototype.reduce1 = function(callback, initialValue) {if(this == null) {throw new TypeError('this is null or not defined');
    }
    if(typeof callback !== "function") {throw new TypeError(callback + 'is not a function');
    }
    const O = Object(this);
    const len = O.length >>> 0;
    let k = 0;
    let accumulator = initialValue;
    // 如果第二个参数为 undefined 的状况下,则数组的第一个有效值(非 empty)作为累加器的初始值
    if(accumulator === undefined) {while(k < len && !(k in O)) {k++;}
        // 如果超出数组界线还没有找到累加器的初始值,则 TypeError
        if(k >= len) {throw new TypeError('Reduce of empty array with no initial value');
        }
        accumulator = O[k++];
    }
    while(k < len) {if(k in O) {accumulator = callback(accumulator, O[k], k, O);
        }
        k++;
    }
    return accumulator;
}
复制代码

对浏览器的了解

浏览器的次要性能是将用户抉择的 web 资源出现进去,它须要从服务器申请资源,并将其显示在浏览器窗口中,资源的格局通常是 HTML,也包含 PDF、image 及其他格局。用户用 URI(Uniform Resource Identifier 对立资源标识符)来指定所申请资源的地位。

HTML 和 CSS 标准中规定了浏览器解释 html 文档的形式,由 W3C 组织对这些标准进行保护,W3C 是负责制订 web 规范的组织。然而浏览器厂商纷纷开发本人的扩大,对标准的遵循并不欠缺,这为 web 开发者带来了重大的兼容性问题。

浏览器能够分为两局部,shell 和 内核。其中 shell 的品种绝对比拟多,内核则比拟少。也有一些浏览器并不辨别外壳和内核。从 Mozilla 将 Gecko 独立进去后,才有了外壳和内核的明确划分。

  • shell 是指浏览器的外壳:例如菜单,工具栏等。次要是提供给用户界面操作,参数设置等等。它是调用内核来实现各种性能的。
  • 内核是浏览器的外围。内核是基于标记语言显示内容的程序或模块。

事件总线(公布订阅模式)

class EventEmitter {constructor() {this.cache = {}
    }
    on(name, fn) {if (this.cache[name]) {this.cache[name].push(fn)
        } else {this.cache[name] = [fn]
        }
    }
    off(name, fn) {let tasks = this.cache[name]
        if (tasks) {const index = tasks.findIndex(f => f === fn || f.callback === fn)
            if (index >= 0) {tasks.splice(index, 1)
            }
        }
    }
    emit(name, once = false, ...args) {if (this.cache[name]) {
            // 创立正本,如果回调函数内持续注册雷同事件,会造成死循环
            let tasks = this.cache[name].slice()
            for (let fn of tasks) {fn(...args)
            }
            if (once) {delete this.cache[name]
            }
        }
    }
}

// 测试
let eventBus = new EventEmitter()
let fn1 = function(name, age) {console.log(`${name} ${age}`)
}
let fn2 = function(name, age) {console.log(`hello, ${name} ${age}`)
}
eventBus.on('aaa', fn1)
eventBus.on('aaa', fn2)
eventBus.emit('aaa', false, '布兰', 12)
// '布兰 12'
// 'hello, 布兰 12'
复制代码

数据类型判断

typeof 能够正确辨认:Undefined、Boolean、Number、String、Symbol、Function 等类型的数据,然而对于其余的都会认为是 object,比方 Null、Date 等,所以通过 typeof 来判断数据类型会不精确。然而能够应用 Object.prototype.toString 实现。

function typeOf(obj) {-   let res = Object.prototype.toString.call(obj).split(' ')[1]
-   res = res.substring(0, res.length - 1).toLowerCase()
-   return res
// 更好的写法
+   return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase()}
typeOf([])        // 'array'
typeOf({})        // 'object'
typeOf(new Date)  // 'date'
复制代码

代码输入后果

function SuperType(){this.property = true;}

SuperType.prototype.getSuperValue = function(){return this.property;};

function SubType(){this.subproperty = false;}

SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function (){return this.subproperty;};

var instance = new SubType();
console.log(instance.getSuperValue());
复制代码

输入后果:true

实际上,这段代码就是在实现原型链继承,SubType 继承了 SuperType,实质是重写了 SubType 的原型对象,代之以一个新类型的实例。SubType 的原型被重写了,所以 instance.constructor 指向的是 SuperType。具体如下:

实现节流函数和防抖函数

函数防抖的实现:

function debounce(fn, wait) {
  var timer = null;

  return function() {
    var context = this,
      args = [...arguments];

    // 如果此时存在定时器的话,则勾销之前的定时器从新记时
    if (timer) {clearTimeout(timer);
      timer = null;
    }

    // 设置定时器,使事件间隔指定事件后执行
    timer = setTimeout(() => {fn.apply(context, args);
    }, wait);
  };
}
复制代码

函数节流的实现:

// 工夫戳版
function throttle(fn, delay) {var preTime = Date.now();

  return function() {
    var context = this,
      args = [...arguments],
      nowTime = Date.now();

    // 如果两次工夫距离超过了指定工夫,则执行函数。if (nowTime - preTime >= delay) {preTime = Date.now();
      return fn.apply(context, args);
    }
  };
}

// 定时器版
function throttle (fun, wait){
  let timeout = null
  return function(){
    let context = this
    let args = [...arguments]
    if(!timeout){timeout = setTimeout(() => {fun.apply(context, args)
        timeout = null 
      }, wait)
    }
  }
}
复制代码

网络劫持有哪几种,如何防备?

⽹络劫持分为两种:

(1)DNS 劫持: (输⼊京东被强制跳转到淘宝这就属于 dns 劫持)

  • DNS 强制解析: 通过批改运营商的本地 DNS 记录,来疏导⽤户流量到缓存服务器
  • 302 跳转的⽅式: 通过监控⽹络出⼝的流量,分析判断哪些内容是能够进⾏劫持解决的, 再对劫持的内存发动 302 跳转的回复,疏导⽤户获取内容

(2)HTTP 劫持: (拜访⾕歌然而⼀直有贪玩蓝⽉的⼴告), 因为 http 明⽂传输, 运营商会批改你的 http 响应内容(即加⼴告)

DNS 劫持因为涉嫌守法,曾经被监管起来,当初很少会有 DNS 劫持,⽽ http 劫持仍然⾮常盛⾏,最无效的方法就是全站 HTTPS,将 HTTP 加密,这使得运营商⽆法获取明⽂,就⽆法劫持你的响应内容。

如何缩小 Webpack 打包体积

(1)按需加载

在开发 SPA 我的项目的时候,我的项目中都会存在很多路由页面。如果将这些页面全副打包进一个 JS 文件的话,尽管将多个申请合并了,然而同样也加载了很多并不需要的代码,消耗了更长的工夫。那么为了首页能更快地出现给用户,心愿首页能加载的文件体积越小越好,这时候就能够应用按需加载,将每个路由页面独自打包为一个文件。当然不仅仅路由能够按需加载,对于 loadash 这种大型类库同样能够应用这个性能。

按需加载的代码实现这里就不具体开展了,因为鉴于用的框架不同,实现起来都是不一样的。当然了,尽管他们的用法可能不同,然而底层的机制都是一样的。都是当应用的时候再去下载对应文件,返回一个 Promise,当 Promise 胜利当前去执行回调。

(2)Scope Hoisting

Scope Hoisting 会剖析出模块之间的依赖关系,尽可能的把打包进去的模块合并到一个函数中去。

比方心愿打包两个文件:

// test.js
export const a = 1
// index.js
import {a} from './test.js'
复制代码

对于这种状况,打包进去的代码会相似这样:

[
  /* 0 */
  function (module, exports, require) {//...},
  /* 1 */
  function (module, exports, require) {//...}
]
复制代码

然而如果应用 Scope Hoisting,代码就会尽可能的合并到一个函数中去,也就变成了这样的相似代码:

[
  /* 0 */
  function (module, exports, require) {//...}
]
复制代码

这样的打包形式生成的代码显著比之前的少多了。如果在 Webpack4 中你心愿开启这个性能,只须要启用 optimization.concatenateModules 就能够了:

module.exports = {
  optimization: {concatenateModules: true}
}
复制代码

(3)Tree Shaking

Tree Shaking 能够实现删除我的项目中未被援用的代码,比方:

// test.js
export const a = 1
export const b = 2
// index.js
import {a} from './test.js'
复制代码

对于以上状况,test 文件中的变量 b 如果没有在我的项目中应用到的话,就不会被打包到文件中。

如果应用 Webpack 4 的话,开启生产环境就会主动启动这个优化性能。

怎么加事件监听,两种

onclick 和 addEventListener

事件流传机制(事件流)

冒泡和捕捉

事件循环机制(Event Loop)

事件循环机制从整体上通知了咱们 JavaScript 代码的执行程序 Event Loop即事件循环,是指浏览器或 Node 的一种解决 javaScript 单线程运行时不会阻塞的一种机制,也就是咱们常常应用 异步 的原理。

先执行 Script 脚本,而后清空微工作队列,而后开始下一轮事件循环,持续先执行宏工作,再清空微工作队列,如此往返。

  • 宏工作:Script/setTimeout/setInterval/setImmediate/ I/O / UI Rendering
  • 微工作:process.nextTick()/Promise  

上诉的 setTimeout 和 setInterval 等都是工作源,真正进入工作队列的是他们散发的工作。

优先级

  • setTimeout = setInterval 一个队列
  • setTimeout > setImmediate 
  • process.nextTick > Promise
for (const macroTask of macroTaskQueue) {handleMacroTask();    
  for (const microTask of microTaskQueue) {handleMicroTask(microTask);  
  }
}
复制代码

Vue 路由守卫有哪些,怎么设置,应用场景等

罕用的两个路由守卫:router.beforeEach 和 router.afterEach

每个守卫办法接管三个参数:to: Route: 行将要进入的指标 路由对象

from: Route: 以后导航正要来到的路由

next: Function: 肯定要调用该办法来 resolve 这个钩子。在我的项目中,个别在 beforeEach 这个钩子函数中进行路由跳转的一些信息判断。判断是否登录,是否拿到对应的路由权限等等。复制代码
退出移动版