什么是三次握手?

是TCP连接时服务器和客户端的相互发送报文,是为了确认双方接受、接受能力是否正常,指定自己的初始化序列号,为后面的可靠性传递做准备。

刚开始客户端处于Closed(关闭)状态,服务器处于Listen(监听)状态。

第一次:客户端给服务器发送一个SYN报文(建立连接),并指明客户端的初始化序列号ISN,此时客户端处于SYN-END(请求连接)状态,首部的同步位SYN=1,初始序列号seq=x,SYN的报文不能携带数据,但是会消耗一个序列号。

第二次:服务器收到后会返回一个SYN报文,指定自己的初始化序列号ISN,同时会把客户端的ISN+1做为自己的ACK(确认字符)值,表示已经收到,此时处于SYN_RCVD(表示已接受到,半列队)状态。在确认报文段中SYN=1,ACK=1,确认号ack=x+1,seq=y。

第三次:客户端收到SYN报文后,会发送ACK报文,将服务器的ISN+1作为ACK的值,此时客户端处于ESTABLISHED(已连接)状态。在确认报文中ACK=1,ack=y+1,seq=x+1,ACK报文可以携带数据了,不携带不消耗序列号。

为什么要三次?

是要确定发送、接收发送、发送接收是否可靠。

什么是四次挥手?(close触发)

是由TCP半关闭造成的,就是结束塔的发送后还能接受来自另一端数据的能力。刚开始都处于ESTANLISHED状态。

如果是客户端发送:

第一次:发送FIN报文,报文中会指定序列号,客户端处于FIN_WAIT1(终止等待1)状态。

第二次:服务器收到后发送ACK报文,接受得序列号+1作为ACK的值,处于CLOSE_WAIT(半关闭)状态。

第三次:服务器收到后发送FIN报文,指定序列号处于LAST_ACK(最后确认)状态,

第四次:客户端收到后发送ACK报文进入TIME_WAIT状态,等一会进入CLOSED(关闭连接)状态,客户端收到关闭连接。

在socket编程中,任何一方执行close()操作就可以产生挥手操作。

什么是VUEX?

是一个为Vue设计的状态管理库,以利用Vue.js的细粒数据响应机制进行高效的状态更新。

        state:存放公用数据/状态的地方;

        getter:类似于vue中的计算属性。

        mutation:修改state的地方,$store.commit([xxx,'name'])

        actions:是mutation的上一级,提交到mutation执行,可调用异步方法。                                            $store.dispach([xxx,'name'])

什么是同源----跨域?

同源:是一种约定,DOM同源/XMLHTTP同源,要求域名、端口号、协议相同。

CROE解决跨域,croe的书写方法和axios一样,通常不需要进行修改,常用。

Jsonp:是一种利用动态 创建script利用src进行跨域,虽然无兼容性问题,但是只能get请求,从别的域加载执行可能会携带恶意代码,不易确定失败。

Nginx反向代理:在vue.confing中proxy

'/api':{
    target :'https://www.easy-mock.com',//设置代理
    target :'http://10.10.29.26:8882', //代理的接口域名以及端口号
    ws:true,//支持ws协议,websocket的缩写,
    changeOrigin: true,// 是否跨域,
    pathRewrite:{ //路径替换
        '^/api':''
    }
}

什么是Promise?

是异步编程的一种解决方案,是一个容器,存放着未来结束的事件结果,语法上说是对象,可以获取异步消息。

三个状态:padding(等待)、fulfiled(成功)、reject(失败)

三个方法:.then(resolve成功、reject失败)

                  .catch(获取异常信息)

                  .funally()都会执行

解决异步无法返回值,new时自身同步,调用方法的时候异步。

什么是fexl布局?

弹性布局由父容器、子容器构成,通常设置主轴和交叉轴来控制子元素的排序方式。

定义子元素的排列方向:

felx-direction:row|row-reverse|column|column-reverse
    //row :默认值,主轴水平方向 左往右对齐👉
    //row-reverse:主轴水方向 右往左对齐👈
    //column:主轴垂直方向 上往下对齐👇
    //column-reverse:主轴垂直方向 下往上对齐👆

轴线属性:

flex-warp:nowrap|warp|warp-reverse
    //nowarp:(默认)不换行
    //warp:换行,在第一行上方
    //warp-reverse:换行,在第一行下方

主轴对齐:

justify-content:flex-start|felx-end|center|space-between|space-around
    //flex-start:(默认值)左对齐
    //flex-end:右对齐
    //center:居中
    //space-between:两端对齐,间隔相等
    //space-around:每个项两侧间隔相等

交叉轴对齐:

align-items:flex-start|flex-end|center|baseline|staretch
    //flex-start:交叉轴的起点对齐
    //flex-end:交叉轴的终点对齐
    //center:交叉轴的中点对齐
    //baseline:项目的第一行文字的基线对齐
    //stretch:默认值,如果项未设置高度或设为auto,将沾满整个容器的高度

多根轴线对齐:

align-content:flex-start|flex-end|center|space-between|space-around|strctch
    //flex-start:与交叉轴的起点对齐
    //flex-end:与交叉轴的终点对齐
    //center:与交叉轴的中点对齐
    //space-between:与交叉轴两端对齐,轴线之间的间隔平均分布
    //space-around:每根轴线两侧的间隔相等
    //stretch:默认值 ,轴线沾满整个交叉轴

数据类型

基本数据类型:undefined、null、Boolean、String、Number、Symbol等等类型在内存中占据固定大小,保存在内存栈中。

引用数据类型:Object、Array、Date、Function、RegExp等等。引用数据类型的值是对象,保存在堆内存中。

在内存栈存储的是对象的变量标识符一级对象在堆内存中储存的存储地址。

什么是深浅拷贝?

浅拷贝:仅仅是复制了引用,彼此之间的操作相互影响。Array==》slice和concat方法

深拷贝:在堆中重新分配内存,不同地址,相同的值,互不影响,复制实例。

JSON.parse();把JSON字符串反序列化为一个js对象

JSON.stringify();把js对象序列化为一个JSON字符串

递归:对属性中所有的应用类型的值进行遍历,知道是基本类型为止

什么是懒加载?

懒加载也叫延迟加载,指在页面中延迟加载页面内容,能够提升用户体验、减少无效的资源加载、防止并发加载的资源过多会阻塞js的加载。

图片懒加载:将地址储存在自定义属性上,当页面滚动时内容马上要在视口内呈现将地址赋值给src。

1、document.documentElement.clientHeight//获取屏幕可视窗口高度
2、element.offsetTop//获取元素相对文档顶部的距离
3、document.doceumentElement.scroliTop//获取浏览器窗口顶部与文档顶部之间的距离,也就是滚动条的距离
可以通过这个三个方法判断 3-2<1 ,从而判断元素是否在可视范围内。

数据懒加载:将地址储存在自定义属性上,当页面滚动时内容马上要在视口内数据赋值。

1、scrollHeight//指元素的总高度
2、scrollTop//当滚动条滚动时,向下拖动滚动条,内容想上滚动的距离。
3、clientHeight//元素可视区的大小,指的是元素内容及其边框所占的空间大小------可视区域的大小
通过 1-2-3==0? 判断滚动条是否到达底部 

路由懒加载:

        通过import()实现

        将路由对应的组件加载成一个个对应的js包,再路由被访问时才将对应的组件加载。

        原理:将路由组件改写成一部组件,只有当函数被调用的时候采取加载对应的组件内容。

什么是守卫?

        全局前置守卫:路由即将改变前,一般项目中进行判断是否登录、是否有路由权限。。。。

reouter.beforeEach((to,from,next)=>{...})
//to=========到哪个页面去
//from=========从哪个页面来
//next==========={回调函数,如果是false,终端导航,如果浏览器URL改变,地址蛔虫知道from路由对
//应的地址,如果next是路径,会中断当前导航去新的导航,可以传任意位置的对象,
//允许设置选项 replace:true,name:'home'以及任何再router-link的to/prop/router.push}

        全局后置守卫:reouter.afterEach(同上)

        组件路由守卫:是写在每个单独的Vue文件里面的路由守卫

beforeRouteEnter(to,from,next)=>{...})
//在进入路由之前调用,组件实例还没有被渲染,无法获取this实例,可以通过传
//一个回调给next来访问,再确认导航的时候执行回调,把组件实例做为回调方法的参数
 
beforeRouteUpdate((to,from,next)=>{...})
//当前路由发生改变,但是组件被复用时调用。
 
beforeRouteLeave((to,from,next)=>{...})
//离开当前路由页面时调用

        路由独享守卫:是再路由配置页面单独给路由配置一个守卫。

export default new VueRouter({routes:[
    {
        path:'/',
        name:'xxx',
        component:'Xxx',
        beforeEnter:(to,from,next)=>{...}
    }]})

DOM

        真实DOM渲染顺序:

        1、解析HTML构建DOM树,并请求css/image/js

        2、CSS文件下载完成,开始构建css树

        3、构建完成后和DOM 一起生成渲染树

        4、布局

        5、显示

        虚拟DOM就是一个用来表示真实DOM的对象,最终会映射到真是环境上,并且它的不依赖真实平台的能力。 页面的更新可以先完全反映在虚拟DOM上,操作内存中的js对象块,将最终的js对象映射成真实DOM,交给浏览器去绘制,减少对真实DOM的操作。

所以说虚拟DOM算法(虚拟DOM+diff算法)操作真实DOM性能高于直接操作真实DOM。

Diff算法(并非Vue专用但凡涉及到虚拟DOM都有)

        能精确比较新旧虚拟DOM中的key变化,提高更新效率。

        是一种对比算法,对比两者谁是新旧虚拟DOM,对比哪个虚拟节点改变,并只更新这个虚拟节点所对应的真实节点

        使用虚拟DOM损耗计算:总损耗 = 虚拟DOM增删改 + 真实DOM差异增删改 + 排版与重绘

        使用真实DOM 损耗计算:总损 = 真实DOM完全增删改+(可能多个节点)排版重绘

原理:新旧虚拟DOM只会再同级对比,是深度优先算法,在patchVnode发生。

对比流程:数据改变触发setter,通过Dep.netify去通知所有订阅者,订阅者会调用patch方法(对比当前同层的虚拟节点是否为同一类型标签),给真实DOM更新相应试图。

总结:

1、diff算法是虚拟DOM技术的必然产物:通过新旧虚拟DOM做对比,将变化的地方更新  在真实DOM上,另外也需要diff高效率执行对比过程,从而降低时间复杂度O(n)---通过updateChildern()高效执行。

2、Vue2中为了降低watcher粒度,每个组织只有一个watcher与之对应,这样才能精确找到发生变化的地方。

3、vue中的diff执行的时候是组件实例执行更新函数时,它会对比上一次渲染结果oldVnde和新的渲染结果,此过程称为patch。

4、diff过程整体遵循深度优先,同层级比较策略,会从头部节点开始对比尝试,如果没有找到相同节点才会遍历查找,查找结束再处理剩下的节点,借助key可以精确找到相同节点,因此patch非常高效。

Vue2与Vue3的区别

        1、Vue3中webpack被隐藏,vue.config.js需要自己创建。

        2、setup函数时Vue3的属性和方法的入口,它可以接受两个参数:props:接收父组件传值,context:上下文,有三个使用参数:attrs、emits、slots,他必须有返回值,async可以省略。

        3、响应式原理区别:

        Vue2中使用Object.defineProperty,进行数据劫持,用obsever进行递归监听,但是如果监听的数组,对于数组的删除、新增属性、通过下标修改不会更新视图,需要调用 set/delete/splice方法。

        Vue3中用的时Proxy(原型对象、原型方法)方法,用proxy代理对象,而不是某个属性。

4、v-fi和v-for的比较:

        Vue2: v-for优先于v-if,每次渲染都先执行循坏在执行判断,浪费性能。

                在外层嵌套template,在这进行判断,再内部循环。

        Vue3:v-if优先于v-for

Vue中data为什么是函数?Vue根实例为什么没有这个限制?

Vue是单页面框架,可能会有很多组件实例,如果形象式定义data,会导致他们共用一个data,造成实例之间的数据污染。 

Vue根实例全局只有一个。

Vue设计原理

        官网上写了定义和特点:vue是一个渐进式的javscript框架,易用,高效且灵活

        渐进式:根其他大型框架不同的是Vue被设计为可以自底向上逐层应用,核心只关注视图图层,不仅易于上手,还便于第三方库的项目整合,vue完全能为复杂的单页面应用提供驱动,核心就是一些声明式渲染,组件系统只关注注释图层,可以作为库再其他项目中取用,也能作为一个大型的框架去搭建项目,这就是渐进式。

Web时代的演变        

web1.0的时代没有前端概念,项目通常由多个单文件组成,每个文件都有HTML、CSS、JS或者java代码,难以维护,于是便出现了MVC开发模式和框架。在MVC模式中前端只完成后端中的view层,前端页面开发效率并不高、前后端职责不清晰。

web2.0时代,自从Ajax技术开始出现,前后端职责分明,前端可以通过Ajax与后端进行整体数据交互,前端只需要开发页面内容,并且ajax技术可以实现部分刷新,减少服务器负载和流量消耗,比如 jQuery,但是缺乏可行的开发模式 承载更复杂的业务需求,页面都挤在一起难以维护。

前后端分离的架构演变:MVC-->MVP-->MVVM

MVC:与后端的类似,Model负责应用数据保存,与后端数据同步,Contoller负责业务逻辑,View负责视图。

 理论上是可行,但是很不方便,然后演变成另一种结构的MVC,加入了User,

这样的模式也会造成数据流混乱的问题

MVP:与MVC很接近,P指的是中间人,它负责view和model之间的数据流,防止直接交互,但是这样view变成了被动试图,而且本身变得很小,但是应用变得很大,导致P体积增大,难以维护。

MVVM: Angular早就把MVVM模式带入前端,跳过了MVP。核心是中间VM层,ViewModel通过数据响应式机制自动响应Model中的数据变化,同时VM会实现更新自动将数据转化试图更新,通过监听V中用户交互更改M中的数据,减少大量操作DOM代码,兼顾开发效率和可维护性。

总结:

1、这三者都是框架模式,他们的目标都是为了解决Model和View的耦合问题。

2、MVC模式出现较早主要应用在后端,分层清晰但是数据流混乱。

3、MVP式MVC的进化,中间人负责MV通讯解决两者耦合问题,但是会臃肿,可维护性不高。

4、 MVVM在前端广泛应用,不仅解决MV耦合问题,还解决了维护两者映射关系的大量代码和DOM操作,提高了开发效率和可读性,同时保持了优越的性能表现。

Vue优化性能方法

        1、路由懒加载

        2、keep-alive缓存页面

        3、区分v-show、v-if使用场景

        4、v-for遍历避免同时使用v-if

        5、vue组件销毁时会自动解绑他的全部指令和时间监听,仅限组件本身事件

        6、图片懒加载、数据懒加载

        7、按需导入

总结

到此这篇关于高频率Vue面试题汇总以及答案的文章就介绍到这了,更多相关高频率Vue面试题内容请搜索阿兔在线工具以前的文章或继续浏览下面的相关文章希望大家以后多多支持阿兔在线工具!

点赞(0)

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部