整理前端知识点(面试)2021-04-06

你对MVVM的理解?

MVVM是什么?

MVVM 模式,顾名思义即 Model-View-ViewModel 模式。它萌芽于2005年微软推出的基于 Windows 的用户界面框架 WPF ,前端最早的 MVVM 框架 knockout 在2010年发布。

Model 层: 对应数据层的域模型,它主要做域模型的同步。通过 Ajax/fetch 等 API 完成客户端和服务端业务 Model 的同步。在层间关系里,它主要用于抽象出 ViewModel 中视图的 Model。

View 层:作为视图模板存在,在 MVVM 里,整个 View 是一个动态模板。除了定义结构、布局外,它展示的是 ViewModel 层的数据和状态。View 层不负责处理状态,View 层做的是 数据绑定的声明、 指令的声明、 事件绑定的声明。

ViewModel 层:把 View 需要的层数据暴露,并对 View 层的 数据绑定声明、 指令声明、 事件绑定声明 负责,也就是处理 View 层的具体业务逻辑。ViewModel 底层会做好绑定属性的监听。当 ViewModel 中数据变化,View 层会得到更新;而当 View 中声明了数据的双向绑定(通常是表单元素),框架也会监听 View 层(表单)值的变化。一旦值变化,View 层绑定的 ViewModel 中的数据也会得到自动更新。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Sqgo27Mx-1617672748174)(C:\Users\何小仙\AppData\Roaming\Typora\typora-user-images\1617672628736.png)]

MVVM的优缺点?

优点:

1.分离视图(View)和模型(Model),降低代码耦合,提高视图或者逻辑的重用性: 比如视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定不同的"View"上,当View变化的时候Model不可以不变,当Model变化的时候View也可以不变。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑
2.提高可测试性: ViewModel的存在可以帮助开发者更好地编写测试代码
3.自动更新dom: 利用双向绑定,数据更新后视图自动更新,让开发者从繁琐的手动dom中解放

缺点:

1.Bug很难被调试: 因为使用双向绑定的模式,当你看到界面异常了,有可能是你View的代码有Bug,也可能是Model的代码有问题。数据绑定使得一个位置的Bug被快速传递到别的位置,要定位原始出问题的地方就变得不那么容易了。另外,数据绑定的声明是指令式地写在View的模版当中的,这些内容是没办法去打断点debug的
2.一个大的模块中model也会很大,虽然使用方便了也很容易保证了数据的一致性,当时长期持有,不释放内存就造成了花费更多的内存
3.对于大型的图形应用程序,视图状态较多,ViewModel的构建和维护的成本都会比较高

你对Vue生命周期的理解?

生命周期是什么

Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模版、挂载Dom -> 渲染、更新 -> 渲染、卸载等一系列过程,我们称这是Vue的生命周期。

各个生命周期的作用

在这里插入图片描述
beforeCreate 组件实例被创建之初,组件的属性生效之前
created 组件实例已经完全创建,属性也绑定,但真实dom还没有生成, e l 还 不 可 用 b e f o r e M o u n t 在 挂 载 开 始 之 前 被 调 用 : 相 关 的 r e n d e r 函 数 首 次 被 调 用 m o u n t e d e l 被 新 创 建 的 v m . el还不可用 beforeMount 在挂载开始之前被调用:相关的 render 函数首次被调用 mounted el 被新创建的 vm. elbeforeMountrendermountedelvm.el 替换,并挂载到实例上去之后调用该钩子
beforeUpdate 组件数据更新之前调用,发生在虚拟 DOM 打补丁之前
update 组件数据更新之后
activited keep-alive专属,组件被激活时调用
deadctivated keep-alive专属,组件被销毁时调用
beforeDestory 组件销毁前调用
destoryed 组件销毁后调用

生命周期示意图

在这里插入图片描述

Vue组件如何通信?

Vue组件通信的方法如下:

  • props e m i t + v − o n : 通 过 p r o p s 将 数 据 自 上 而 下 传 递 , 而 通 过 emit+v-on: 通过props将数据自上而下传递,而通过 emit+von:propsemit和v-on来向上传递信息。
  • EventBus: 通过EventBus进行信息的发布与订阅
  • vuex: 是全局数据管理库,可以通过vuex管理全局的数据流
  • $attrs l i s t e n e r s : V u e 2.4 中 加 入 的 listeners: Vue2.4中加入的 listeners:Vue2.4attrs/$listeners可以进行跨级的组件通信
  • provide/inject:以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效,这成为了跨组件通信的基础

还有一些用solt插槽或者ref实例进行通信的,使用场景过于有限就不赘述了。

虚拟DOM实现原理?

  • 虚拟DOM本质上是JavaScript对象,是对真实DOM的抽象
  • 状态变更时,记录新树和旧树的差异
  • 最后把差异更新到真正的dom中

回流(重排)

什么是回流(重排),什么情况下会触发回流

  • 当元素的尺寸或者位置发生了变化,就需要重新计算渲染树,这就是回流
  • DOM元素的几何属性(width/height/padding/margin/border)发生变化时会触发回流
  • DOM元素移动或增加会触发回流
  • 读写offset/scroll/client等属性时会触发回流
  • 调用window.getComputedStyle会触发回流

如何减少回流

  • 使用class替代style,减少style的使用
  • 使用resize、scroll时进行防抖和节流处理,这两者会直接导致回流
  • 使用visibility替换display: none,因为前者只会引起重绘,后者会引发回流
  • 批量修改元素时,可以先让元素脱离文档流,等修改完毕后,再放入文档流
  • 避免触发同步布局事件,我们在获取offsetWidth这类属性的值时,可以使用变量将查询结果存起来,避免多次查询,每次对offset/scroll/client等属性进行查询时都会触发回流
  • 对于复杂动画效果,使用绝对定位让其脱离文档流,复杂的动画效果会频繁地触发回流重绘,我们可以将动画元素设置绝对定位从而脱离文档流避免反复回流重绘。

图片

浏览器解析渲染页面过程

在这里插入图片描述

  • 解析HTML,生成DOM树
  • 解析CSS,生成CSSOM树
  • 将DOM树和CSSOM树关联,生成渲染树(Render Tree)
  • 布局render树(Layout/reflow),负责各元素尺寸、位置的计算
  • 绘制render树(paint),绘制页面像素信息
  • 将像素发送给GPU,展示在页面上。(Display)

介绍一下浏览器缓存位置和优先级

1.Service Worker
2.Memory Cache(内存缓存)
3.Disk Cache(硬盘缓存)
4.Push Cache(推送缓存)
5.以上缓存都没命中就会进行网络请求

谈一下EventLoop

图片
这其中大家需要了解几个概念:调用栈、同步/异步任务、宏任务/微任务
JavaScript本身是单线程,也就是同一时刻只能干一件事,JS任务包含了同步任务和异步任务,遇到执行函数会将其放入调用栈(先进后出)中,遇到setTimeout/setInterval等异步任务时,会把它放入到消息队列中,等主线程的任务执行完成以后,再回过头执行消息队列中的异步任务,如果异步任务中仍然有异步任务,会继续放入消息队列,以此类推,便形成了一个事件循环。
异步任务:

setTimeout
setInterval

异步任务又分为宏任务和微任务,promise就属于微任务.

谈一下防抖和节流

防抖和节流

防抖和节流都是希望在同一时间内,不要重复触发请求。一般场景用在搜索和网页滚动事件中。

区别:

防抖主要是在规定时间内只触发一次,如果再次调用,时间从新计算。
节流主要是在固定时间内只触发一次。比如每间隔1秒触发一次。

防抖

动作停止后的时间超过设定的时间时执行一次函数。注意:这里的动作停止表示你停止了触发这个函数,从这个时间点开始计算,当间隔时间等于你设定时间,才会执行里面的回调函数。如果你一直在触发这个函数并且两次触发间隔小于设定时间,则函数一直不会执行。
简单实现:

function debance(fn, delay) {
    
    
  let timer = null;
  return () => {
    
    
    if (timer) {
    
    
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
    
    
      fn();
    }, delay);
  };
}

window.addEventListener(
  "scroll",
  debance(() => {
    
    
    console.log(111);
  }, 1000)
);
防抖应用场景:

1. search搜索联想,用户在不断输入值时,用防抖来节约请求资源
2. window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次

节流

一定时间内执行的操作只执行一次,也就是说即预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期。
简单实现:

 //方法一:设置一个标志
 function throttle(fn, delay) {
    
    
   let flag = true;
   return () => {
    
    
     if (!flag) return;
     flag = false;
     timer = setTimeout(() => {
    
    
       fn();
       flag = true;
     }, delay);
   };
 }
 //方法二:使用时间戳
  function throttle(fn, delay) {
    
    
   let startTime=new Date()
   return () => {
    
    
     let endTime=new Date()
     if (endTime-startTime>=delay){
    
    
       fn()
       startTime=endTime
     }else{
    
    
       return
     }
   };
 }
 window.addEventListener(
   "scroll",
   throttle(() => {
    
    
     console.log(111);
   }, 1000)
 );
  节流应用场景:
  鼠标不断点击触发,mousedown(单位时间内只触发一次)
  监听滚动事件,比如是否滑到底部自动加载更多(懒加载),用throttle来判断

JS运行机制

什么是浏览器的同源策略

同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键安全机制。
什么是源:协议、域名与端口。这三者任何一个不一样的话,就算是跨域
什么是限制:不是一个源的文档,没有权限去操作另一个源的文档

1)怎么解决跨域问题

1.JSONP(只支持GET请求)

通过 script 标签的异步加载来实现的。利用script标签不受同源策略的限制,天然可以跨域的特性。

<script>
var script = document.createElement('script');
script.type = 'text/javascript';

script.src = 'https://api.asilu.com/geo/&callback=jsonp';//这个是获取当前经纬度的接口
document.head.appendChild(script);//创建并添加script标签到<head>下

// 回调执行函数
function jsonp(res) {
    
    
    console.log(res);//打印jsonp返回的信息
}
</script>

2.CORS(现代浏览器普遍跨域解决方案)

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信

介绍一下HTTP/2.0新特性

  • 多路复用: 即多个请求都通过一个TCP连接并发地完成
  • 服务端推送: 服务端能够主动把资源推送给客户端
  • 新的二进制格式: HTTP/2采用二进制格式传输数据,相比于HTTP/1.1的文本格式,二进制格式具有更好的解析性和拓展性
  • header压缩: HTTP/2压缩消息头,减少了传输数据的大小

说说HTTP/3.0

尽管HTTP/2解决了很多1.1的问题,但HTTP/2仍然存在一些缺陷,这些缺陷并不是来自于HTTP/2协议本身,而是来源于底层的TCP协议,我们知道TCP链接是可靠的连接,如果出现了丢包,那么整个连接都要等待重传,HTTP/1.1可以同时使用6个TCP连接,一个阻塞另外五个还能工作,但HTTP/2只有一个TCP连接,阻塞的问题便被放大了。

由于TCP协议已经被广泛使用,我们很难直接修改TCP协议,基于此,HTTP/3选择了一个折衷的方法——UDP协议,HTTP/2在UDP的基础上实现多路复用、0-RTT、TLS加密、流量控制、丢包重传等功能。

CSRF攻击

什么是CSRF攻击

CSRF即Cross-site request forgery(跨站请求伪造),
是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。

假如黑客在自己的站点上放置了其他网站的外链,例如"www.weibo.com/api,默认情况下,浏览器会带着weibo.com的cookie访问这个网址,如果用户已登录过该网站且网站没有对CSRF攻击进行防御,那么服务器就会认为是用户本人在调用此接口并执行相关操作,致使账号被劫持。

如何防御CSRF攻击

  • 验证Token:浏览器请求服务器时,服务器返回一个token,每个请求都需要同时带上token和cookie才会被认为是合法请求
  • 验证Referer:通过验证请求头的Referer来验证来源站点,但请求头很容易伪造
  • 设置SameSite:设置cookie的SameSite,可以让cookie不随跨域请求发出,但浏览器兼容不一

猜你喜欢

转载自blog.csdn.net/HXX548888/article/details/115454207