高频前端面试题

高频面试题

文章目录

  • 高频面试题
      • 一、HTML
          • 1、你都做过哪些兼容性问题?
          • 2、如何提高页面性能?
          • 3、谈谈你对H5的理解?
          • 4、浏览器从输入网址都看到网页都发生了什么?
          • 5、重绘和重排?
          • 6、缓存?
          • 7、状态码?
          • 8、!DOCTYPE html 是干什么的,有什么用?
      • 二、CSS
          • 1、display:none; 和visibility:hidden;的区别是什么?
          • 2、CSS 优先级和权重值如何计算
          • 3、如何触发BFC,以及BFC的作用
          • 4、CSS盒模型
          • 5、如何水平垂直居中一个元素
          • 6、css实现一个三角形
          • 7、如何实现左边固定宽,右边自适应布局
          • 8、如何实现6px字体
          • 9、移动端1px边框怎么设置
          • 10、px、em、rem、vh、vw分别是什么
          • 11、css可继承的属性有哪些
      • 三、JavaScript
          • 1、call、apply、bind的区别
          • 2、数据类型有哪些
          • 3、如何检测数据类型
          • 4、各语句的区别
          • 5、闭包
          • 6、原型和原型链
          • 7、继承
          • 8、递归和递归优化
          • 9、ajax工作原理和封装
          • 10、跨域
          • 11、事件流和事件委托
          • 12、事件循环
          • 13、防抖和节流
          • 14、深克隆和浅克隆
          • 15、cookie、sessionStorage和localStorage的区别
          • 16、get和post请求的区别
          • 17、new操作符都做了哪些事情
          • 18、XSS攻击和CSRF攻击
          • 19、垃圾回收机制
          • 20、常用DOM操作
          • 21、AMD、CMD、ES6、CommonJS的区别
      • 四、ES6
          • 1、let、const、var的区别
          • 2、箭头函数和普通函数的区别
          • 3、promise的实现原理和封装
          • 4、forEach、for in、for of三者区别
          • 5、set、map分别是什么
          • 6、symbol的理解
          • 7、新增哪些数组方法
          • 8、新增哪些字符串方法
          • 9、新增哪些对象方法
          • 10、async...await
      • 五、Vue
          • 1、生命周期都有哪些,以及在这些生命周期中都做过哪些事情
          • 2、组件通信
          • 3、页面通信
          • 4、$set是干什么的
          • 5、$nextTick是干什么的
          • 6、mixin是干什么的
          • 7、简单说说MVVM的理解
          • 8、watch和computed的区别
          • 9、v-if和v-show的区别
          • 10、为什么不能v-for和v-if一起使用
          • 11、key的作用是什么,值写index和id哪个更好
          • 12、过滤器怎么使用
          • 13、vuex五大核心分别是干什么的
          • 14、如何调用mutations和actions的方法
          • 15、vue-router常写属性都有什么
          • 16、路由守卫都有哪些以及都做过哪些事情,三个参数分别是干什么的
          • 17、hash和history模式的区别
          • 18、说说常用指令有哪些,如何自定义指令
          • 19、vue插槽如何使用
          • 20、vue单页应用优缺点
          • 21、为什么做SSR,如何实现
          • 22、如何实现路由懒加载
          • 23、less如何设置全局样式
          • 24、scoped的作用是什么
          • 25、 r o u t e r 和 router和 routerroute的区别
          • 26、data:{}和data(){return {}} 的区别
          • 27、axios的配置、封装、拦截和跨域
          • 28、cli各版本构建项目的命令和启动命令
          • 29、简单谈谈你对vue3.0的理解
          • 30、简单说说双向绑定的原理
          • 31、做过哪些vue的性能优化
          • 32、vue的diff算法和虚拟dom
          • 33、vuex页面刷新后数据丢失?和history模式刷新404问题?
          • 34、Vue 开发中如何使用全局状态常量?你都用这个状态常量做什么事情
          • 35、动态路由
      • 六、React
          • 1、调用 setState 之后发生了什么?
          • 2、react 生命周期函数
          • 3、为什么虚拟 dom 会提高性能?
          • 4、react diff 原理
          • 5、React 中 refs 的作用是什么?
          • 6、展示组件和容器组件之间有何不同?
          • 7、类组件和函数式组件之间有何不同?
          • 8、createElement 和 cloneElement 有什么区别?
          • 9、简述 flux 思想
          • 10、了解 redux 么,说一下 redux
          • 11、什么是JSX?
          • 12、React Hooks是什么
          • 13、class 组件有什么不足
      • 七、小程序
          • 1、简单描述下微信小程序的相关文件类型
          • 2、简述微信小程序原理
          • 3、小程序的双向绑定和vue哪里不一样
          • 4、小程序页面间有哪些传递数据的方法
          • 5、小程序的生命周期函数
          • 6、小程序组件通信
      • 八、常见编程题
          • 1、数组去重
          • 2、数组排序
          • 3、统计字符串中出现次数最多的字符
          • 4、手写数组filter方法
          • 5、手写数组map方法
          • 6、函数柯里化
          • 7、数组扁平化
          • 8、手写bind方法
          • 9、数组交集、差集
          • 10、连续重复最长的项
          • 11、手写queryString
          • 12、手写splice方法
      • 九、其他
          • 1、webpack的基本配置
          • 2、git的常用命令
          • 3、项目的工作流程
          • 4、项目中你都负责哪块
          • 5、平时是如何进行自己的技能提升的
          • 6、你还有什么想要了解的
          • 7、你都封装过哪些组件

一、HTML

1、你都做过哪些兼容性问题?

HTML兼容性:

h5新标签只能兼容到ie9,如果想要兼容ie低版本浏览器,需要引入html5shiv.js文件,其cdn写法如下:


CSS兼容性:

1.1、媒体查询兼容性,ie9以下不支持媒体查询,需要引入response.js文件,其cdn写法如下:


1.2、CSS Hack:

1.2.1、属性前缀:例如 IE6能识别下划线和星号,IE7能识别星号,但不能识别下划线,IE6~IE10都认识"\9",但firefox前述三个都不能认识。

.red { 
	_color: red; /* ie6 */
	*color: red; /* ie7 */
	color: red\9; /* ie8/9/10 */
}

1.2.2、选择器前缀:例如 IE6能识别 * html .class{},IE7能识别 +html .class{}或者*:first-child+html .class{}。

*.red {} /* ie6 */
+.red {} /* ie7 */

1.2.3、条件注释:

针对所有IE(注:IE10+已经不再支持条件注释):


针对IE6及以下版本:


这类Hack不仅对CSS生效,对写在判断语句里面的所有代码都会生效。

1.3、厂商前缀:谷歌-webkit-、火狐-moz-、IE-ms-、欧朋-o-

1.4、其它兼容性:

1.4.1、ie老版本浮动造成的双边距问题:display:inline;

1.4.2、图片间隙:父盒子设置font-size: 0; 或者图片设置display: block;

1.4.3、块元素默认高度:overflow: hidden;

**JavaScript兼容性:**一般使用渐进增强和优雅降级的方式来解决兼容性问题。

// 优雅降级
var xhr = null;
if(XMLHttpRequest){
	xhr = new XMLHttpRequest();
}else{
	xhr = new ActiveXObject('Microsoft.XMLHTTP');
}

// 渐进增强
// 前边实现上传文件的基本功能
// 后边再判断如果支持拖拽事件,就实现拖拽上传

2、如何提高页面性能?

2.1、图片压缩、合并(精灵图)、使用字体图标代替小图片、使用base64、图片懒加载

2.2、css、js的压缩、封装复用

2.3、减少重排操作,例如使用transform书写动画效果,在for循环结束后再去操作dom等

2.3、使用CDN网络托管

2.4、数据懒加载、数据按需加载(上拉加载)、分页

2.5、路由懒加载

2.6、利用缓存来缓存文件

2.7、频繁触发的事件进行防抖和节流

2.8、异步加载

2.9、减少闭包,递归优化,使用高效的算法

2.10、webpack优化:去除无用代码treeShaking、组件按需加载、使用chunck、模板预编译等

2.11、字库用gb2312不要utf-8,一个汉字少一个字节


3、谈谈你对H5的理解?

Html5是Web中核心语言HTML的规范,是 HyperText Markup Language 5 的缩写,H5提供新的标签元素,使代码变的更有语义;提供了大量api,如本地存储、离线存储、webworker、websocket、filereader、地理定位、拖拽等;提供了更加酷炫的CSS3新特性,如过渡、变形、动画、阴影、渐变等。


4、浏览器从输入网址都看到网页都发生了什么?

4.1、域名解析成ip地址

4.2、客户端发送一个带有SYN标志的数据包给服务端(三次握手,第一次)

4.3、服务端收到后,回传一个带有SYN/ACK标志的数据包以示传达确认信息(三次握手,第二次)

4.4、客户端再回传一个带ACK标志的数据包,代表握手结束,连接成功(三次握手,第三次)

4.5、服务端处理数据并返回数据

4.6、客户端请求关闭连接(四次挥手,第一次)

4.7、服务端确认是否还有数据要传输(四次挥手,第二次)

4.8、服务端没有要传输的数据了,准备关闭连接(四次挥手,第三次)

4.9、客户端断开连接(四次挥手,第四次)

4.10、浏览器解析HTML,生成DOM树,解析CSS,生成CSS规则树

4.11、DOM树和CSS规则树合并成渲染树,开始渲染

4.12、执行JavaScript脚本


5、重绘和重排?

重排也叫回流,当元素因为规模尺寸,布局,隐藏等改变而需要重新构建时则成为重排。

重绘:一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局则叫重绘。

重绘不一定重排,但是重排一定重绘。


6、缓存?

6.1、浏览器缓存:就是把一个已经请求过的资源拷贝一份存储起来,当下次需要该资源时, 浏览器会根据缓存机制决定直接使用缓存资源还是再次向服务器发送请求。分为:

强制缓存:请求头设置cache-control:

​ max-age缓存的时间

​ no-cache:不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。

​ no-store:直接禁止浏览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。

​ public:可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器。

​ private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。

协商缓存:请求头设置last-modified/etag

1.Etag要优于Last-Modified。Last-Modified的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的Last-Modified其实并没有体现出来修改,但是Etag每次都会改变确保了精度;

2.在性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值;

3.在优先级上,服务器校验优先考虑Etag。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lP9m27us-1629198968567)(F:\offcn\course\第6阶段视频\第6-8天-面试题\offcn\高频面试题\4.png)]

6.2、H5缓存:

本地存储:localStorage永久存储、sessionStorage临时存储

离线缓存:在html标签上设置 manifest 属性 引入cache文件(CACHE缓存文件,NETWORK不缓存文件,FALLBACK当资源不可访问时,代替的文件)

6.3、更新缓存文件:1、更新manifest文件;2、通过javascript操作:window.applicationCache.update();3、清除浏览器缓存;4、带版本号,根据版本号判断。


7、状态码?

1字头:信息,服务器收到请求,需要请求者继续执行操作

2字头:成功,操作被成功接收并处理

3字头:重定向,需要进一步的操作以完成请求

4字头:客户端错误,请求包含语法错误或无法完成请求

5字头:服务器错误,服务器在处理请求的过程中发生了错误

101:切换协议。

200:请求成功。一般用于GET与POST请求

203:非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本

204:无内容。服务器成功处理,但未返回内容。

301:永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。

302:临时移动。

304:未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。

305:使用代理。所请求的资源必须通过代理访问

307:临时重定向。

400:客户端请求的语法错误,服务器无法理解

404:服务器无法根据客户端的请求找到资源(网页)

405:客户端请求中的方法被禁止

500:服务器内部错误,无法完成请求

502:作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应

503:由于超载或系统维护,服务器暂时的无法处理客户端的请求。

505:服务器不支持请求的HTTP协议的版本,无法完成处理


8、!DOCTYPE html 是干什么的,有什么用?

1、声明文档类型是html5类型的文档。2、声明了则是标准模式,兼容ie高版本;不声明则是混杂模式,兼容ie低版本。


二、CSS

1、display:none; 和visibility:hidden;的区别是什么?

display:none; 彻底消失,释放空间。能引发页面的reflow回流(重排)。

visibility:hidden; 就是隐藏,但是位置没释放,好比opacity:0; 不引发页面回流。


2、CSS 优先级和权重值如何计算

内嵌样式>内部样式>外部样式>导入式

!important > 内嵌 1000 >Id 100 > class=[]=伪类 10 > tag=伪元素 1 > ( * + > ~) 0


3、如何触发BFC,以及BFC的作用

BFC:块级格式化上下文block formatting context,是一个独立渲染区域。规定了内部box如何布局,并且与这个区域外部毫不相干。

触发:float的值不是none;position的值不是static或者relative;display的值是inline-block、block、table-cell、flex、table-caption或者inline-flex;overflow的值不是visible。

作用:避免margin重叠;自适应两栏布局;清除浮动。


4、CSS盒模型

盒模型由:外边距margin、边框border、内边距padding、内容content四个部分组成

标准盒模型大小=border+padding+content

怪异盒模型大小=content

转怪异盒模型:box-sizing:border-box;

转标准盒模型:box-sizing:content-box;


5、如何水平垂直居中一个元素

5.1、弹性盒子

.box{
  display: flex;
  justify-content: center;
  align-items: center;
}

5.2、定位

.box{
  position: relative;
}
.box .sub{
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  /*margin-left: 负的宽度的一半*/
  /*margin-top: 负的高度的一半*/
}

6、css实现一个三角形
.triangle{
  width: 0;
  height: 0;
  border: 100px solid transparent;
  border-left-color: red;
}

7、如何实现左边固定宽,右边自适应布局

7.1、圣杯布局

#container { padding-left: 200px; padding-right: 150px; } #container .column { float: left; } #center { width: 100%; } #left { width: 200px; margin-left: -100%; position: relative; right: 200px; } #right { width: 150px; margin-right: -150px; }

7.2、双飞翼布局

  
#container { width: 100%; } .column { float: left; } #center { margin-left: 200px; margin-right: 150px; } #left { width: 200px; margin-left: -100%; } #right { width: 150px; margin-left: -150px; }

7.3、等高布局(假等高)互补的内外边距

.parent{
  overflow: hidden;
}
.left, .right{
  margin-bottom: -10000px;
  padding-bottom: 10000px;
}

7.4、等高布局(真等高)弹性盒子

.parent{
  display: flex;
}
.child{
  flex: 1;
}

7.5、calc

  
.column{ float: left; } #left{ width: 100px; } #right{ width: 200px; } #center{ width: calc(100% - 100px - 200px); }

7.6、浮动

  
.column{ float: left; } #left{ width: 100px; } #right{ width: 200px; } #center{ margin-left: 100px; margin-right: 200px; }

8、如何实现6px字体
.font{
  font-size: 12px;
  transform: scale(.5);
}

9、移动端1px边框怎么设置
/* 方法1 */
.border{
  width: 100%;
  height: 1px;
  background: red;
}
/* 方法2 */
.border{
  border-image: url(border.png)
}
/* 方法3 */
.border{
  box-shadow: 0 0 0 1px #000;
}

10、px、em、rem、vh、vw分别是什么

px物理像素,绝对单位;em相对于父级字体大小,相对单位;rem相对于html的字体大小,相对单位;vh相对于屏幕高度的大小,相对单位;vw相对于屏幕宽度的大小,相对单位。


11、css可继承的属性有哪些

可继承的属性:文本类:text-indent、text-align、line-height、word-spacing、letter-spacing、text-transform、direction、color;

字体类:font、font-family、font-weight、font-size、font-style、font-variant、font-stretch、font-size-adjust;

其它类:visibility、caption-side、border-collapse、border-spacing、empty-cells、table-layout、list-style-type、list-style-image、list-style-position、list-style、quotes、cursor、page、page-break-inside、windows、orphans等


三、JavaScript

1、call、apply、bind的区别

这三个都是用来定义上下文的,call、apply会指定上下文并执行函数;而bind终身定 死上下文但是不执行函数,并返回新的函数。 其中call和apply传入参数的形式有别,call是单独罗列,逗号隔开参数;apply是数 组。 函数.call(上下文对象,参数,参数,参数); 函数.apply(上下文对象,[参数,参数,参数]);

var obj = {
 a: 10
}

function fun(b, c){
 console.log(this.a + b + c);
}

fun.call(obj, 3, 4);
fun.apply(obj, [3, 4]);
fun = fun.bind(obj); // 返回新的函数
fun(3,4);

2、数据类型有哪些

基本类型:数字number、字符串string、布尔boolean、undefined、null、symbol

引用类型:数组array、函数function、对象object


3、如何检测数据类型

typeof 能够检测:数字、字符串、布尔、undefined、symbol、function

instanceof 能够检测:数组

Object.prototype.toString.call() 万能法


4、各语句的区别

4.1、for和for…in和for…of的区别

for循环,遍历整个数组

for…in加强循环,不光可以遍历数组,还可以遍历对象和其原型上的方法

for…of遍历数组和可枚举的对象

4.2、switch和if的区别

switch用于判断精准的值

if用于判断值的范围

4.3、while和do…while的区别

while当符合条件时则执行

do…while先执行一次,然后再判断是否符合条件,比while要多执行一次

4.4、break和continue的区别

break是跳出当前循环并终止循环

continue是跳出当前循环并执行下一次循环


5、闭包

闭包就是函数能够记忆住当初定义时候的作用域,不管函数到哪里执行了,永远都能够 记住那个作用域,并且会遮蔽新作用域的变量。可预测状态容器;实现模块化,实现变量的私有封装;可以实现迭代器。 闭包缺点:1.闭包有一个非常严重的问题,那就是内存浪费问题,这个内存浪费不仅仅 因为它常驻内存,更重要的是,对闭包的使用不当的话会造成无效内存的产生;2.性能问题 使用闭包时,会涉及到跨作用域访问,每次访问都会导致性能损失。 因此在脚本中,最好小心使用闭包,它同时会涉及到内存和速度问题。不过我们可以通过把跨作用域变量存储在局部变量中,然后直接访问局部变量,来减轻对执行速度的影响。

function foo(){
    var a = 0;
    function f(){
      a++;
      return a;
    }
    return f;
}
var res = foo();
res(); 
res();
res();
console.log(res()); // 4 a的值被存储在内存中不会被释放掉

6、原型和原型链

原型:每一个引用类型都有一个隐式原型__ proto __ ,每一个函数都有一个显示原型prototype,该属性指向它的原型对象。

原型链:某个对象的原型又有自己的原型,直到某个对象的原型为null为止,组成这条的最后一环,这种一级一级的链就是原型链。


7、继承

7.1、原型链继承

 /**
 * 缺点:引用类型的属性被所有实例共享,
 * 在创建Child 的实例时, 不能向Person传参
 */
   function Person() {
    this.name = "xiaopao";
   }
   Person.prototype.getName = function () {
    console.log(this.name);
   };
   function Child() {}
   Child.prototype = new Person();

7.2、借用构造函数继承(经典继承)

/*
优点:
1.避免了引用类型的属性被所有实例共享
2.可以在Child中向Parent传参
缺点:
1.只是子类的实例,不是父类的实例
2.方法都在构造函数中定义,每次创建实例都会创建一遍方法
*/
   function Child() {
    Person.call(this);
   }

7.3、组合继承

/*
优点:融合原型链继承和构造函数的优点,是JavaScript中最常用的继承模式
缺点:调用了两次父类构造函数
组合继承最大的问题是无论什么情况下,都会调用两次超类型构造函数:一次是在创建子
类型原型的时候,另一次是在子类型构造函数内部)
*/
   function Child(name, age) {
    Parent.call(this, name); // 第二次调用 Parent()
    this.age = age;
   }
   Child.prototype = new Parent(); // 第一次调用 Parent()

7.4、原型式继承

 // 缺点: 包含引用类型的属性值始终都会共享相应的值, 这点跟原型链继承一样
   function CreateObj(o) {
    function F() {}
    F.prototype = o;
    return new F();
   }
   var person = {
    name: "xiaopao",
    friend: ["daisy", "kelly"],
   };
   var person1 = CreateObj(person);

7.5、寄生式继承 可以理解为在原型式继承的基础上增加一些函数或属性

 // 缺点:跟借用构造函数一样,每次创建对象都会创建一遍方法

   var ob = {
    name: "xiaopao",
    friends: ["lulu", "huahua"],
   };

   function CreateObj(o) {
    function F() {} // 创建一个构造函数F
    F.prototype = o;
    return new F();
   }

   // 上面CreateObj函数 在ECMAScript5 有了一新的规范写法,Object.create(ob) 效果是一样的 , 看下面代码
   var ob1 = CreateObj(ob);
   console.log(ob1.name); // xiaopao

7.6、寄生组合式继承

// 优点:完美继承
// 缺点:代码繁多,使用起来十分麻烦
   function Parent(name) {
    this.name = name;
    this.colors = ["red", "blue", "green"];
   }

   Parent.prototype.sayName = function () {
    console.log(this.name);
   };

   function Child(name, age) {
    Parent.call(this, name);
    this.age = age;
   }

   function CreateObj(o) {
    function F() {}
    F.prototype = o;
    return new F();
   }


   // Child.prototype = new Parent(); // 这里换成下面
   function prototype(child, parent) {
    var prototype = CreateObj(parent.prototype);
    prototype.constructor = child;
    child.prototype = prototype;
   }
   prototype(Child, Parent);


   var child1 = new Child("xiaopao", 18);

   console.log(child1);

7.7、es6 继承

 class Child extends Parent {}

8、递归和递归优化

递归就是函数自己调用自己。但是又不能无限的调用自己,需要有一个出口,否则会成为死循环。函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。

// 循环求1-5的所有数的和
var sum = 0;
for(var i = 1; i <= 5; i++){
	sum += i;
}
console.log(sum) // 15

//递归实现1-5的所有数的和
function sum(n){
	if(n === 1){
		return 1;
	}
	return n + sum(n-1);
}
console.log(sum(5)); //15

尾递归优化是解决递归调用栈溢出的方法。尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。

// 上例递归进行尾递归优化
function sum(n, m = 0){
	if(n === 1){
		return 1 + m;
	}
	return sum(n-1, n + m);
}
console.log(sum(5)); //15

// 或者while优化
function sum(n, m = 0){
	while(n >= 1){
		return sum(n - 1, n + m);
	}
	return m;
}
console.log(sum(5)); // 15


9、ajax工作原理和封装

1.创建XMLHttpRequest对象。 2.设置请求方式。open() 3.调用回调函数。onreadystatechange 4.发送请求。send()

 function ajax(options) {
    const { type, dataType, data, timeout, url, success, error } = options;
    var params = formatParams(data);
    var xhr;
    //考虑兼容性
    if (window.XMLHttpRequest) {
      xhr = new XMLHttpRequest();
    } else if (window.ActiveObject) {
      //兼容IE6以下版本
      xhr = new ActiveXobject("Microsoft.XMLHTTP");
    }
    //启动并发送一个请求
    if (type == "GET") {
      xhr.open("GET", url + "?" + params, true);
      xhr.send();
    } else if (type == "POST") {
      xhr.open("post", url, true);
      //设置表单提交时的内容类型
      //Content‐type数据请求的格式
      xhr.setRequestHeader(
        "Content‐type",
        "application/x‐www‐form‐urlencoded"
      );
      xhr.send(params);
    }

    // 设置有效时间
    setTimeout(function () {
      if (xhr.readySate != 4) {
        xhr.abort();
      }
    }, timeout);

    // 接收
    // options.success成功之后的回调函数 options.error失败后的回调函数
    //xhr.responseText,xhr.responseXML 获得字符串形式的响应数据或者XML形式的响应数据
    xhr.onreadystatechange = function () {
      if (xhr.readyState == 4) {
        var status = xhr.status;
        if ((status >= 200 && status < 300) || status == 304) {
          success && success(xhr.responseText, xhr.responseXML);
        } else {
          error && error(status);
        }
      }
    };
  }

  //格式化请求参数
  function formatParams(data) {
    var arr = [];
    for (var name in data) {
      arr.push(
        encodeURIComponent(name) + "=" + encodeURIComponent(data[name])
      );
    }
    arr.push(("v=" + Math.random()).replace(".", ""));
    return arr.join("&");
  }

10、跨域

跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的。其 实我们通常所说的跨域是狭义的,是由浏览器同源策略限制的一类请求场景。同源策略SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR 等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地 址,也非同源。

方法1:跨域资源共享CORS跨域,就是服务端在HTTP返回头上加上“AccessControll-Allow-Origin:*”。 “Access-Controll-Allow-METHODS:GET, POST” DELETE、PATCH请求类型会发出OPTIONS预检请求。

方法2:代理跨域,webpack-dev-server里面的proxy配置项。config中的 ProxyTable

方法3:JSONP,利用页面srcipt没有跨域限制的漏洞,用script的src引入它,然后页 面内定义回调函数,jQuery中$.ajax({dataType: ‘jsonp’})。

方法4: iframe跨域,配合window.name或者 location.hash或者document.domain 一起使用

方法5:nginx反向代理接口跨域,通过nginx配置一个代理服务器(域名与domain1 相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中 domain信息,方便当前域cookie写入,实现跨域登录。

方法6:jquery的ajax跨域,dataType:‘jsonp’


11、事件流和事件委托

事件流一般分三个阶段:1、捕获阶段(由外向内) 2、目标阶段 (执行阶段) 3、冒泡阶段(由内向外)

阻止事件冒泡e.stopPropagation() 阻止默认动作e.preventDefault()

事件委托:就是把事件委托给父级,利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。


12、事件循环

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mVVPC7Iq-1629198968570)(F:\offcn\course\第6阶段视频\第6-8天-面试题\offcn\高频面试题\2.png)]

同步任务进入主线程,异步任务进入Event Table并注册函数 当指定的事情完成时,Event Table会将这个函数移入Event Queue。 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执 行。 上述过程会不断重复,也就是常说的Event Loop(事件循环)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3oRvsoTe-1629198968574)(F:\offcn\course\第6阶段视频\第6-8天-面试题\offcn\高频面试题\3.png)]

      console.log("script start");

      setTimeout(function () {
        console.log("setTimeout");
      }, 0);

      Promise.resolve()
        .then(function () {
          console.log("promise1");
        })
        .then(function () {
          console.log("promise2");
        });

      console.log("script end");
      /* 执行结果为:script start, script end, promise1, promise2, setTimeout因为Promise是微任务,主线程会在同步任务做完后先清空微任务队列,再执行宏任务队列 */

微任务是由JavaScript自身发起,包括:process.nextTick、promise、MutationObserver

宏任务是由宿主发起的,如浏览器、node。包括:setTimeout、setInterval、setImmediate、postMessage


13、防抖和节流
// 节流:在计时器内部清除计时器,有节奏的执行事件
        function throttle(callback, delay = 1000){
            let timer = null;
            function f(){
                if(!timer){
                    timer = setTimeout(() => {
                        callback && callback.call(this);
                        clearTimeout(timer);
                        timer = null;
                    }, delay);
                }
            }
            return f;
        }
      
// 防抖:在计时器前边清除计时器,只执行最后一次事件,能够无限延长执行时间
        function debounce(callback, delay = 1000) {
            let timer = null;
            function f() {
                clearTimeout(timer);
                timer = setTimeout(() => {
                    callback && callback.call(this);
                }, delay);
            }
            return f;
        }

14、深克隆和浅克隆

浅克隆:同值也同址。浅拷贝是指源对象与拷贝对象共用一份实体,仅仅是引用的变量不同(名称不同)。对其中任何一个对象的改动都会影响另外一个对象。如:Object.assign;=等号赋值;slice截取。

深克隆:同值不同址。深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。如:JSON.parse(JSON.stringify());

  function deepClone(target) {
    // 定义一个变量
    let result;
    // 如果当前需要深拷贝的是一个对象的话
    if (typeof target === "object") {
      // 如果是一个数组的话
      if (Array.isArray(target)) {
        result = []; // 将result赋值为一个数组,并且执行遍历
        for (let i in target) {
          // 递归克隆数组中的每一项
          result.push(deepClone(target[i]));
        }
        // 判断如果当前的值是null的话;直接赋值为null
      } else if (target === null) {
        result = null;
        // 判断如果当前的值是一个RegExp对象的话,直接赋值
      } else if (target.constructor === RegExp) {
        result = target;
      } else {
        // 否则是普通对象,直接for in循环,递归赋值对象的所有值
        result = {};
        for (let i in target) {
          result[i] = deepClone(target[i]);
        }
      }
      // 如果不是对象的话,就是基本数据类型,那么直接赋值
    } else {
      result = target;
    }
    // 返回最终结果
    return result;
  }

15、cookie、sessionStorage和localStorage的区别

15.1、cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递,而sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下
15.2、存储大小限制也不同,cookie数据不能超过4K,同时因为每次http请求都会携带cookie、所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大
15.3、数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭之前有效;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭
15.4、作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localstorage在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的
15.5、web Storage支持事件通知机制,可以将数据更新的通知发送给监听者
15.6、web Storage的api接口使用更方便


16、get和post请求的区别

GET在浏览器回退时是无害的,而POST会再次提交请求。

GET产生的URL地址可以被Bookmark,而POST不可以。

GET请求会被浏览器主动cache,而POST不会,除非手动设置。

GET请求只能进行url编码,而POST支持多种编码方式。

GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。

GET请求在URL中传送的参数是有长度限制的,而POST么有。

对参数的数据类型,GET只接受ASCII字符,而POST没有限制。

GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。

GET参数通过URL传递,POST放在Request body中


17、new操作符都做了哪些事情

构造函数中没有显示的创建Object对象,实际上后台自动创建了一个空对象,直接给this对象赋值属性和方法,this即指向创建的对象。没有return返回值,后台自动返回了该对象,该对象继承构造函数的原型

// 模拟构造函数实现
 var Book = function(name) {
   this.name = name;
 };
 //正常用法
 var js = new Book('js');
 //使用代码模拟,在非IE浏览器中测试,IE浏览器不支持
 var javascript = {};
 javascript.__proto__ = Book.prototype;
 Book.call(javascript, 'js');

18、XSS攻击和CSRF攻击

XSS:跨站脚本攻击Cross site script,因叫css容易让人误会所以改成了xss。比如一个JSON数据:

      var obj = [
        {
          id: 1,
          name: "",
          age: 12,
        }
      ];

在不该出现script代码的地方出现了,引发一些潜在的危险。 XSS漏洞,能让人们在网页里面插入一段有功能的语句。 XSS 全称“跨站脚本”,是注入攻击的一种。其特点是不对服务器端造成任何伤害, 而是通过一些正常的站内交互途径,例如发布评论,提交含有 JavaScript 的内容文本。这时服务器端如果没有过滤或转义掉这些脚本,作为内容发布到了页面上,其他用户访问这个 页面的时候就会运行这些脚本。 防范: ① 用正则表达式阻止用户提交带有<、eval、script等危险字眼的语句 ② 显示的时候不要直接用innerHTML,而是用innerText,或者将<转义。

CSRF 的全称是“跨站请求伪造”,而 XSS 的全称是“跨站脚本”。看起来有点相 似,它们都是属于跨站攻击——不攻击服务器端而攻击正常访问网站的用户,但前面说 了,它们的攻击类型是不同维度上的分类。CSRF 顾名思义,是伪造请求,冒充用户在站内 的正常操作。我们知道,绝大多数网站是通过 cookie 等方式辨识用户身份(包括使用服务 器端 Session 的网站,因为 Session ID 也是大多保存在 cookie 里面的),再予以授权的。 所以要伪造用户的正常操作,最好的方法是通过 XSS 或链接欺骗等途径,让用户在本机(即 拥有身份 cookie 的浏览器端)发起用户所不知道的请求。 就是说,如果用户不老老实实写姓名,写了一个个


19、垃圾回收机制

一般来说没有被引用的对象就是垃圾,就是要被清除, 有个例外如果几个对象引用形成一个环,互相引用,但根本访问不到它们,这几个对象也是垃圾,也要被清除。 垃圾回收的方法主要有两种:一种是标记清除,即用完之后的变量 赋值成null,另一种 是引用计数,将使用完的对象的引用计数,如果为0则回收


20、常用DOM操作

createElement 创建

appendChild末尾添加

insertBefore 前边插入

cloneNode(true) 克隆

removeChild() 移除

parentNode父节点

childNodes // 全部子节点

firstChild // 第一个子节点

lastChild // 最后一个子节点

previousSibling // 上一个兄弟节点

nextSibling // 下一个兄弟节点

获取dom节点:document.getElementById() 、document.getElementsByTagName() 、document.getElementsByClassName() 、document.getElementsByName() 、document.querySelector() 、document.querySelectorAll()


21、AMD、CMD、ES6、CommonJS的区别

CommonJS:模块引用(require) 模块输出(exports) 模块标识(module) ES6:模块引用(import) 模块输出(export) 前者支持动态导入,也就是 require(${path}/xx.js),后者目前不支持。 前者是同步导入,因为用于服务端,文件都在本地,同步导入即使卡住主线 程影响也不大。而后者是异步导入,因为用于浏览器,需要下载文件,如果也采用同 步导入会对渲染有很大影响。 前者在导出时都是值拷贝,就算导出的值变了,导入的值也不会改变,所以 如果想更新值,必须重新导入一次。但是后者采用实时绑定的方式,导入导出的值都 指向同一个内存地址,所以导入值会跟随导出值变化 AMD、CMD都使用define定义模块,require引入模块,区别在于AMD是前置依赖, CMD是就近依赖

      // AMD   依赖必须一开始就声明
      define(["./a", "./b"], function (require, factory) {
        // do something...
      });

      // CMD  
      define(function(require, factory) {
        var a = require('./a'); // 依赖就近书写
        // do something...
      });

四、ES6

1、let、const、var的区别

var声明变量存在变量提升,let和const不存在变量提升

let、const都是块级局部变量 ,存在暂时性死区

const 的特性和 let 完全一样,不同的只是const声明时候必须赋值,赋值基本类型时,只能进行一次赋值,即声明后不能再修改,赋值引用类型时,内存地址不能修改

同一作用域下let和const不能声明同名变量,而var可以


2、箭头函数和普通函数的区别

2.1、箭头函数的this是定义时决定的,普通函数是看调用方法。

2.2、箭头函数不能成为构造函数

2.3、箭头函数不能使用async/await

2.4、箭头函数不能使用Generator函数,不能使用yeild关键字

2.5、箭头函数不能使用call、apply、bind来修改this指向

2.6、箭头函数不绑定arguments

2.7、箭头函数不具有prototype原型对象,不具有super


3、promise的实现原理和封装

promise一共有三种状态,分别是pedding初始状态 、resolved成功的状态、 rejected失败的状态。传入两个参数,一个是resolve,执行then的方法,一个是reject,执行catch的方法或者then的第二个参数的回调。promise一旦状态改变就不可在修改。promise的链式调用实际上是返回的一个新的promise,而非return this。

// 简版promise
function Promise(executor){ //executor执行器
    let self = this;
    self.status = 'pending'; //等待态
    self.value  = undefined; // 表示当前成功的值
    self.reason = undefined; // 表示是失败的值
    function resolve(value){ // 成功的方法
        if(self.status === 'pending'){
            self.status = 'resolved';
            self.value = value;
        }
    }
    function reject(reason){ //失败的方法
        if(self.status === 'pending'){
            self.status = 'rejected';
            self.reason = reason;
        }
    }
    executor(resolve,reject);
}

Promise.prototype.then = function(onFufiled,onRejected){
    let self = this;
    if(self.status === 'resolved'){
        onFufiled(self.value);
    }
    if(self.status === 'rejected'){
        onRejected(self.reason);
    }
}

4、forEach、for in、for of三者区别

forEach更多的用来遍历数组
for in 一般用来遍历对象或json,可以遍历对象的原型
for of一遍用来遍历数组对象和可枚举对象,不能遍历原型
for in循环出的是key,for of循环出的是value


5、set、map分别是什么

set对象:允许你存储任何类型的唯一值,无论是原始值或者是对象引用。Set是值得集合,不能通过get方法获取值,因为set只有值。能通过迭代器进行for…of遍历。Set的值是唯一的可以做数组去重。

var set = new Set(['1',undefined,{},2,[3,4]]);
set.size; // 5
set.add(5);
set.delete('1'); // true
set.has('2'); // false
set.keys(); // SetIterator
set.values(); // SetIterator
set.entries(); // SetIterator
// set对象可遍历
set.forEach();

map对象:Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。

var myMap = new Map();
var keyObj = {};
myMap.set(keyObj, "和键 keyObj 关联的值");
myMap.get(keyObj); // "和键 keyObj 关联的值"
myMap.size // 1
myMap.has(keyObj); // true
myMap.delete(keyObj); // true
myMap.clear(); 
myMap.keys(); // MapIterator	键组成的对象
myMap.values(); // MapIterator  值组成的对象
myMap.entries(); // MapIterator	键值对组成的对象
// map对象可遍历
myMap.forEach((value, key) => {
  console.log(value, key)
})
for(var [key, value] of myMap){
	console.log(key, value); //  {}, "和键 keyObj 关联的值"
} 

6、symbol的理解

ES6 引入了一种新的原始数据类型 Symbol ,表示独一无二的值,最大的用法是用来定义对象的唯一属性名

let sy = Symbol("KK");
console.log(sy);   // Symbol(KK)
typeof(sy);        // "symbol"
 
// 相同参数 Symbol() 返回的值不相等
let sy1 = Symbol("kk"); 
sy === sy1;       // false

// 写法1
let syObject = {};
syObject[sy] = "kk";
console.log(syObject);    // {Symbol(key1): "kk"}
 
// 写法2
let syObject = {
  [sy]: "kk"
};
console.log(syObject);    // {Symbol(key1): "kk"}
 
// 写法3
let syObject = {};
Object.defineProperty(syObject, sy, {value: "kk"});
console.log(syObject);   // {Symbol(key1): "kk"}

Symbol 值作为属性名时,该属性是公有属性不是私有属性,可以在类的外部访问。但是不会出现在 for…in 、 for…of 的循环中,也不会被 Object.keys() 、 Object.getOwnPropertyNames() 返回。如果要读取到一个对象的 Symbol 属性,可以通过 Object.getOwnPropertySymbols() 和 Reflect.ownKeys() 取到。

for (let i in syObject) {
  console.log(i);
}    // 无输出
 
Object.keys(syObject);                     // []
Object.getOwnPropertySymbols(syObject);    // [Symbol(key1)]
Reflect.ownKeys(syObject);                 // [Symbol(key1)]

7、新增哪些数组方法

forEach:forEach()会遍历数组, 循环体内没有返回值,forEach()循环不会改变原来数组的内容, forEach()有三个参数, 第一个参数是当前元素, 第二个参数是当前元素的索引, 第三个参数是当前元素所属的数组

map:map()的主要作用, 其实是创建一个新的数组

filter:filter()主要是过滤的, 用来过滤数组中不满足条件的元素, 把满足条件的元素放到新的数组里, 并且不会改变原数组

every:会遍历数组, 在循环体内写条件, 如果每一项都是true, 就会返回true, 只要有一个是false, 就会返回false

some:遍历数组的每一项, 然后根据循环体内的条件去判断, 只要有一个是true, 就会停止循环

reduce:接收一个函数作为累加器, 数组中每个值(从左到右)开始缩减, 最终为一个值

Array.from():用于将两类对象变成数组。一类是类数组对象,一类是可遍历对象。

Array.of():用于将一组值,转换为数组

find() 和 findIndex():用于找出第一个符合条件的数组成员和下标。

fill():方法使用给定值填充一个数组

includes():检查是否包含某个值


8、新增哪些字符串方法

startsWith():返回布尔值,表示参数字符串是否在原字符串的头部

endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部

includes():返回布尔值,表示是否找到了参数字符串

repeat():返回一个新字符串,表示将原字符串重复n次

padStart():开始位置填充

padEnd():结束位置填充

trimStart():消除字符串头部的空格

trimEnd():消除字符串尾部的空格

matchAll():返回一个正则表达式在当前字符串的所有匹配


9、新增哪些对象方法

Object.is():判断两个值是否相等

Object.assign():用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

Object.getOwnPropertyDescriptors():返回指定对象所有自身属性(非继承属性)的描述对象

Object.setPrototypeOf(),Object.getPrototypeOf():用来读取或设置当前对象的prototype对象

Object.keys():用于返回一个数组,成员的参数是对象自身的所有可遍历属性的键名

Object.values():返回值是一个数组,成员是对象自身的(不含继承的)所有可遍历属性的值。

Object.entries():返回一个数组,成员是对象自身(不含继承的)所有可遍历属性的键值对数组,Symbol 属性的值会被过滤。

Object.fromEntries():是Object.entries 的逆操作,将一个键值对数组转为对象。


10、async…await

async…await是Generator函数的语法糖,将*改成async,将yield换成await。 是对Generator函数的改进, 返回promise。 异步写法同步化,遇到await先返回,执行完异步再执行接下来的. 内置执行器, 无需next()


五、Vue

1、生命周期都有哪些,以及在这些生命周期中都做过哪些事情

beforeCreate创建之前;无法获取响应数据

created创建之后,可以在这加个loading事件和进行数据请求

beforeMount挂载前 ,在这结束loading,还做一些初始数据的获取,实现函数自执行

mounted挂载后 ,在这发起后端请求,拿回数据,配合路由钩子做一些事情

beforeUpdate数据更新之前

updated数据更新完成之后

beforeDestroy销毁之前 ,你确认删除XX吗?或者确认退出吗?

destroyed销毁之后 ,当前组件已被删除,清空相关内容,在这获取不到dom了


2、组件通信

父传子:props、 a t t r s / attrs/ attrs/listeners、 c h i l d r e n 、 children、 childrenroot、provide/inject、$refs

子传父: e m i t 、 emit、 emitparent、

同级传:eventBus、vuex


3、页面通信

url拼接参数:"/a?a1=a1",接收页面:this.$route.query.a1

query传参:{path: ‘a’, query: {a2:‘a2’}},接收页面:this.$route.query.a2

params传参:{name: ‘a’, params: {a3:‘a3’}},接收页面:this.$route.params.a3

动态路由传参:/path/a4 ,接收页面:this.$route.params.id,路由:path: “/a/:id”


4、$set是干什么的

当数据变化但没有更新视图时使用,例如对象新增加的属性,数组新增加的成员

this.$set(obj,"key","value")

5、$nextTick是干什么的

在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

例如:在created生命周期中想要操作dom就可以使用

this.$nextTick(()=>{ … })可以在mounted之前的生命周期中操作dom


6、mixin是干什么的

提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。

var mixin = {
  data: function () {
    return {
      message: 'hello',
      foo: 'abc'
    }
  }
}

new Vue({
  mixins: [mixin],
  data: function () {
    return {
      message: 'goodbye',
      bar: 'def'
    }
  },
  created: function () {
    console.log(this.$data)
    // => { message: "goodbye", foo: "abc", bar: "def" }
  }
})

7、简单说说MVVM的理解

MVVM 是 Model-View-ViewModel 的缩写。 Model代表数据模型,也可以在 Model中定义数据修改和操作的业务逻辑。 View 代表UI 组件,它负责将数据模型转化成 UI 展现出来。 ViewModel 监听模型数据的改变和控制视图行为、处理用户交互,简单理 解就是一个同步View 和 Model的对象,连接Model和View。 在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也 会立即反应到View 上。 ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起 来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关 注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维 护完全由 MVVM 来统一管理。


8、watch和computed的区别

Watch只能监听data中的数据变化,computed不需要,watch可以进行异步操作, computed不可以,computed不修改原始数据,通过return返回处理的数据,可以包含大 量的逻辑运算


9、v-if和v-show的区别

9.1、v-show 只是简单的控制元素的 display 属性,而 v-if 才是条件渲染(条件为真,元 素将会被渲染,条件为假,元素会被销毁);

9.2、v-show 有更高的首次渲染开销,而 v-if 的首次渲染开销要小的多;

9.3、v-if 有更高的切换开销,v-show 切换开销小;

9.4、v-if 有配套的 v-else-if 和 v-else,而 v-show 没有

9.5、v-if 可以搭配 template 使用,而 v-show 不行


10、为什么不能v-for和v-if一起使用

v-for 优先级是比 v-if 高

永远不要把 v-if 和 v-for 同时用在一个元素上,带来性能方面的浪费(每次渲染都会先循环再进行条件判断)

如果避免出现这种情况,则在外层嵌套 template (页面渲染不生成dom节点),再这一层进行 v-if 判断,然后再内部进行 v-for 循环


如果条件出现再循环内部,可通过计算属性 computed 提前过滤掉那些不需要显示的项

computed:{
	items:function(){
		return this.list.filter(function(item){
			return item.isShow
		})
	}
}

11、key的作用是什么,值写index和id哪个更好

key是为每个vnode指定唯一的id,在同级vnode的Diff过程中,可以根据key快速的进 行对比,来判断是否为相同节点, 利用 key 的唯一性生成 map 对象来获取对应节点,比遍历方式更快,指定key后,可以 保证渲染的准确性(尽可能的复用 DOM 元素。)赋值时应优先使用id。


12、过滤器怎么使用
// 全局使用
Vue.filter('globalFilter', function(){
    // ...
})

// 局部使用
filters: {
    formatMoney(num) {
		// ...
    },
}

过滤器{{ money | formatMoney }}


13、vuex五大核心分别是干什么的

state:Vuex中的基本数据,辅助函数mapState

getters:即从store的state中派生出的状态,有点类似计算属性,辅助函数mapGetters

mutations:是更改Vuex中的store中的状态的唯一方法,是同步的,辅助函数mapMutations

actions:Action 提交的是 mutation,而不是直接变更状态。 Action 可以包含任意异步操作。辅助函数mapActions

Modules:Vuex 允许我们将 store 分割到模块(module)。每个模块拥有自己的 state、mutations、actions、getters、甚至是嵌套子模块——从上至下进行类似的分割


14、如何调用mutations和actions的方法
调用mutations:$store.commit('mutations中定义的方法')

调用actions:$store.dispatch('actions中定义的方法')

actions调用mutations中的方法:

fn(context){

    context.commit('mutations中定义的方法');

}

15、vue-router常写属性都有什么

router-link常用属性:

to表示目标路由的链接

replace设置replace属性的话,当点击时,会调用roter.replace()而不是router.push(),所以导航后不会留下history记录,也就是不能回退到上一个页面

append设置append属性后,则在当前路径前添加基路径,例如,我们从/a导航到一个相对路径b,如果没有配置append,则路径为/b,如果配了,则为/a/b

tag 有时候想要渲染成某种标签,例如

  • 。于是我们使用tag prop 类指定何种标签,同样它还是会监听点击,触发导航。
  • active-class 设置链接激活时使用的css类名。默认值可以通过路由的构造选项linkActiveClass来全局配置, 默认值为 ‘router-link-active‘

    exact “是否激活”,默认是false 。

    vue-router常用属性:

    path路由路径

    name路由名字

    component导入路由组件

    redirect路由重定向

    mode路由模式

    children子路由

    meta路由元信息


    16、路由守卫都有哪些以及都做过哪些事情,三个参数分别是干什么的

    全局守卫:beforeEach(登录拦截)、afterEach

    路由独享守卫:beforeEnter(部分路由的登录拦截)

    组件内守卫:beforeRouteEnter(权限管理)、beforeRouteUpdate、beforeRouteLeave

    路由全局解析守卫:beforeResolve(这里根据单页面name的指向不同,去访问的接口域名也不同)

    三个参数:to:去哪,from:从哪来,next:下一步

    当从a页面离开进入b页面时触发的生命周期
        1.beforeRouteLeave:路由组件的组件离开路由前钩子,可取消路由离开。
        2.beforeEach: 路由全局前置守卫,可用于登录验证、全局路由loading等。
        3.beforeEnter: 路由独享守卫
        4.beforeRouteEnter: 路由的组件进入路由前钩子。
        5.beforeResolve:路由全局解析守卫
        6.afterEach:路由全局后置钩子
        7.beforeCreate:组件生命周期,不能访问this。
        8.created:组件生命周期,可以访问this,不能访问dom。
        9.beforeMount:组件生命周期
        10.deactivated: 离开缓存组件a,或者触发a的beforeDestroy和destroyed组件销毁钩子。
        11.mounted:访问/操作dom。
        12.activated:进入缓存组件,进入a的嵌套子组件(如果有的话)。
        13.执行beforeRouteEnter回调函数next。
    

    17、hash和history模式的区别

    hash模式就是url后面写#锚点,由于 hash 值变化不会导致浏览器向服务器发出请求,而且 hash 改变会触发 hashchange 事件(hashchange只能改变 # 后面的url片段);更关键的一点是,因为hash发生变化的url都会被浏览器记录下来,从而你会发现浏览器的前进后退都可以用了,所以人们在 html5 的 history 出现前,基本都是使用 hash 来实现前端路由的

    history模式:hash 能兼容到IE8, history 只能兼容到 IE10;hash 本来是拿来做页面定位的,如果拿来做路由的话,原来的锚点功能就不能用了。其次,hash 的传参是基于 url 的,如果要传递复杂的数据,会有体积的限制,而 history 模式不仅可以在url里放参数,还可以将数据存放在一个特定的对象中。history api可以分为两大部分:切换(back、forward、go)和修改(pushState,replaceState)。history模式的问题:就怕刷新,


    18、说说常用指令有哪些,如何自定义指令

    v-if :如果是真则渲染节点,否则不渲染节点

    v-if、v-else 和 v-else-if :类似js的if…else判断语句

    v-show :通过display:none;控制元素显示隐藏

    v-for :循环,v-for的优先级高于v-if,不推荐一起使用

    v-bind :绑定属性,

    v-on :绑定事件,

    .stop 阻止事件继续传播

    .prevent 事件不再重载页面

    .capture 使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理

    .self 只当在 event.target 是当前元素自身时触发处理函数

    .once 事件将只会触发一次

    .passive 告诉浏览器你不想阻止事件的默认行为

    v-model :数据双向绑定

    .lazy 默认情况下,v-model同步输入框的值和数据。可以通过这个修饰符,转变为在change事件再同步。

    .number 自动将用户的输入值转化为数值类型

    .trim 自动过滤用户输入的首尾空格

    v-text 和 v-html :用来更新textContent和输出真正的html结构

    v-pre :主要用来跳过这个元素和它的子元素编译过程。

    v-cloak :保持在元素上直到关联实例结束时进行编译。

    v-once :关联的实例,只会渲染一次。之后的重新渲染,实例极其所有的子节点将被视为静态内容跳过,这可以用于优化更新性能。

    // 自定义指令 v-focus
      directives: {
        focus: {
          // 指令的定义
          inserted: function(el) {
            el.focus();
          },
        },
      },
    

    19、vue插槽如何使用
    // 比如新建一个 组件
    
    // 使用插槽