更新面试题系列二(vue相关)

262 阅读5分钟

1. 浏览器输入一个网址的解析过程

1、用户输入网址,浏览器发起dns(域名解析)请求查询缓存:
2、TCP的三次握手:建立一个TCP连接,需要客户端和服务器总共发送3个包;
    - 客户端发送连接的请求;
    - 服务端回应一个确认应答;
    - 客户端在回应一个确认应答,连接成功。    
3、发起http请求:客户端向服务器发送http请求;
4、服务器响应;
5、浏览器解析渲染页面:
    - 浏览器将html、svg等解析成dom tree,将css资源解析成css tree
    - js通过dom tree和css tree生成render tree来完成网页初始化。 

2、vue中的diff算法

1.Diff的由来?
Vue利用双向绑定原理,实现了视图层和数据层的同时更新,在数据层发生变化的时候利
用虚拟DOM去更新对应的DOM树,那么新DOM树和旧DOM树如何去比对,DOM-diff主要就是
用来做这个事情,将新旧DOM树进行比对,更新在真实dom上。

2.如何实现?
 — vue中的DOM-diff 也叫patch ,意思就是打补丁。
    diff整体过程遵循深度优先,同层比较的策略。
    两个节点的比较会根据它们是否有子节点和文本节点做不同的操作:
    对比子节点:首尾节点四次对比尝试,找不到才会通过遍历查找;
    借助key可以非常精确的找到相同节点;
    创建节点:新的VNode中有而旧的oldVNode中没有,就在旧的oldVNode中创建。
    删除节点:新的VNode中没有而旧的oldVNode中有,就从旧的oldVNode中删除。
    更新节点:新的VNode和旧的oldVNode中都有,就以新的VNode为准,更新旧的oldVNode。

3、vue的虚拟dom

虚拟dom本质上是一个原生的js对象去描述一个dom节点,是对真实dom的一层抽象。
优点:
1、无需手动操作dom,减少对原生的dom操作,提升性能;
2、跨平台的兼容,因为虚拟dom本质上是js对象与平台无关。
缺点:
首次渲染大量的dom,由于做了一层虚拟dom的计算,会比直接innerHtml慢。

4、vue的响应式原理

vue2.x中数据响应式:
1、使用数据劫持+观察者模式实现;
2、对象内部通过Object.defineProperty来劫持对象属性;
3、创建一个observer,将每一个属性转化为getter/setter形式来侦测数据的变化;
4、每个属性都拥有自己的dep属性,存放他所依赖的watcher,当属性变化后会通知自己对应的watcher去更新。

vue3.0中使用proxy来实现数据的响应式:
proxy的优势:
proxy可以直接监听对象而非属性;
proxy可以直接监听数组;
proxy返回的是一个新的对象,而object只能遍历对象属性进行修改。
缺点:兼容性不好。
function defineReactive(obj,key,val){
    Object.defineProperty(obj,key,{
        // 递归多层
        observe(obj);
        get(){
            return val
        }
        set(newVal){
            if(newVal !== val){
                observer(newVal);
                val = newVal;
            }
        }
    })
}
function observer(obj){
    Object.keys(obj).forEach(key=>{
        defineReactive(obj,key,obj[key])
    })
}

5、vue3.0的新特性

1、静态树提升:vue3的编译器能检测到什么是静态的,然后将其提升,降低渲染成本;
2、静态属性提升:diff算法时跳过这些属性不改变的节点;
3、基于proxy的数据响应式:组件实例初始化速度提高,节省内存开销,存在低浏览器兼容问题;
4、使用composition api,新增setup选项;
5、支持ts、树摇优化等。

6、vue中scoped的实现原理

1scoped的作用是它的css样式只能作用于当前vue组建,使组件样式不相互污染。
2、实现原理:通过postcss实现;
   postcss给组件中所有dom添加一个独立无二的动态属性,给css选择器额外添加一个对应的属性选择器,来选择组件中的dom,这种做法使得样式只作用于含有该属性的dom元素(组件内部的dom)。
3scoped穿透:
   如何修改组件内部引入的第三方插件的样式?
   `外层 >>> 第三方组件`
        样式`

7、vue的key为什么不要用index ?

key在虚拟dom中得作用主要是可以更高效得更新虚拟dom。

1、使用index作为key值,在删除或者添加元素得时候,其他没有改变得元素的
   key值也会随着变化,这时候在diff计算得时候就会重新去比对渲染,会影响性能。
2、如果index是select的选项,其中第二个被选中,删除第一个,那第三个就会
   变成被选中的状态,产生bug。
3key需要使用唯一的id,删除新增并不会影响原有的元素和key的关系,原有的
   元素都不会被重新渲染,在select中的使用也不会出现上述的bug。     

8、vue中data为什么是个函数?

因为vue组件可能存在多个实例,如果用对象,会导致它们共用一个data对象,
那么状态变更会影响所有组件,这是不合理的;
采用data的形式状态变更会返回全新的data对象,规避多实例的状态污染。

9、vue.set出现的原因?

因为给响应式对象添加属性,以及直接修改数组下标来改值都不会触发视图更新;
当添加不存在的属性,会把新的属性进行响应式跟踪,触发对象的dep收集到的watcher去更新;

vue中数组考虑性能原因没有用defineProperty对数组的每一次进行拦截,
而是对7种数组方法进行重写:pushshiftpopspliceunshiftsortreverse。
在vue中修改数组的索引和长度是无法监测到的,重写后的方法中会手动触发通知该数组的所有依赖
进行更新。

10、.vue文件是如何转成可执行的代码的?

vue的编译是将template转化为render函数的过程:
1、将模版字符串转换成抽象语法树AST;
2、对ast进行静态节点标记,主要用来做虚拟dom的渲染优化;
3、使用ast生成render函数代码。

后续待更新~