前端八股文(vue篇)

发布时间:2023年12月21日

一.vue中的key的作用

key的作用主要是为了高效的更新虚拟dom。另外vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换内部属性而不会触发过渡效果。

二.接口请求一般放在哪个生命周期?为什么要这样做?

接口请求可以放在钩子函数created,beforeMount,mounted中进行调用,因为在这三个钩子函数中,data已经创建,可以将服务器端返回的数据进行赋值。

但推荐在created钩子函数中调用异步请求,因为在created钩子函数中调用异步请求有以下几个优点

  • 能够更快获取到服务器端数据,减少页面loading时间
  • SSR不支持beforeMount,mounted钩子函数,所以放在created中有助于代码一致性
  • created是在模板渲染成html调用,即通常初始化某些元素属性值,然后再渲染成视图。如果在mounted钩子函数中请求数据可能导致页面闪屏问题

三.说一下vue中computed和methods的区别是什么?

首先从表现形式上面来看,computed和methods的区别大致有下面4点:

  1. 在使用时,computed可以当做属性使用,而methods则当做方法调用
  2. computed可以具有getter和setter,因此可以赋值,而methods不行。
  3. computed无法接收多个参数,而methods可以
  4. computed具有缓存,而methods没有

如果从底层来看的话,computed和methods在底层实现上面还有很大的区别。

vue对于methods的处理比较简单,只需要遍历methods配置中的每一个属性,将其对于的函数使用bind绑定当前组价实例后复制其引用到组件实例中即可

四.nextTick的作用是什么?他的实现原理是什么?

作用:vue更新DOM是异步更新的,数据变化,DOM的更新不会马上完成,nextTick的回调是在下次DOM更新循环结束之后执行的延迟回调。

实现原理:nextTick主要使用了宏任务和微任务。根据执行环境分别尝试采用

  • Promise :可以将函数延迟到当前函数调用栈最末端
  • ?MutationObserver:是H5新增加的一个功能,其功能是监听dom节点的变动,在所有dom变动完成后,执行回调函数
  • setImmediate:用于中断长时间运行的操作,并在浏览器完成其他操作(如事件和显示更新)后立即运行回调函数
  • 如果以上都不行则采用setTimeout把函数延迟到DOM更新之后再使用,原因是宏任务消耗大于微任务,优先使用微任务,最后使用消耗最大的宏任务。

五.vue组件的data为什么必须是函数

组件中的data写成一个函数,数据以函数返回值形式定义。这样每复用一次组件,就会返回一份新的data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得所有组件实例共用一份data,就会造成一个变了会导致全变的结果

六.Proxy相比于defineProperty的优势在哪里?

Vue3.x改用了Proxy来替代Object.defineProperty

原因在于Object.defineProperty本身存在一些问题:

  • Object.defineProperty只能劫持对象属性的getter和setter方法。
  • Object.defineProperty不支持数组(可以监听数组,不过数组方法无法监听自己重写),更准确的说是不支持数组的各种API(所以Vue重写了数组方法)

而相比于Object.defineProperty,Proxy的优点在于:

  • Proxy是直接代理劫持整个对象
  • Proxy可以监听对象和数组的变化,并且有多达13种拦截方法。

七.说一下watch与computed的区别是什么?以及他们的使用场景分别是什么?

区别如下:

  • ? ? ? ?都是观察数据变化的(相同点)
  • 计算属性将会混入到vue实例中,所以需要监听自定义变量;watch监听data,props里面数据的变化。
  • computed有缓存,它依赖的值发生了变化才会重新计算,watch没有;
  • watch支持异步,computed不支持;
  • watch是一对多;computed是多对一(监听属性依赖于其他元素)
  • watch监听函数接收两个参数,第一个是最新值,第二个是输入之前的值;
  • computed属性是函数时,都有get和set方法,默认走get方法,get方法必须有返回值。

watch的参数:

  • deep:深度监听
  • immediate:组件加载立即触发回调函数执行

computed的缓存原理:

computed本质是一个惰性的观察者,当计算数据存在于data或者是props里时挥别警告;


八.scoped是如何实现样式穿透

首先说一下什么场景下需要scoped样式穿透

在很多项目中,会出现这么一种情况,即:引用了第三方组件,需要在组件中局部修改第三方组件的样式,而又不想去除scoped属性造成的组件之间的样式污染。此时只能通过特殊的方式,穿透scoped。

有三种方式来实现样式穿透:

方法一:

使用::v-deep操作符(>>>的别名)

如果希望scoped样式中一个选择器能够作用更深,例如影响子组件,可以使用>>>操作符;

<style scoped>

    .a >>> .b { /* ... */ }

</style>

上述代码将会编译成:

.a[data-v-f3f3eg9] .b { /* ... */ }

后面的类名没有data属性,所以能选到子组件里面的类名。

方法二:

定义一个含有scoped属性的style标签之外,在定义一个不含scoped属性的style标签,即在一个vue组件定义一个全局的style标签,一个含有作用域的style标签。

<style>

/* global styles */

</style>



<style scoped>

/* local styles */

</style>

此时,我们只需要将修改的第三方样式的css写到第一个style标签里面即可、

第三个方法:

上面的方法一需要单独书写一个不含有 scoped 属性的 style 标签,可能会造成全局样式的污染。

更推荐的方式是在组件的外层 DOM 上添加唯一的 class 来区分不同组件,在书写样式时就可以正常针对针对这部分 DOM 书写样式。


九.说一下vue模板编译的原理是什么?

简单说,Vue的编译过程就是将template转化为render函数的过程。会经历以下阶段:

  • 生成AST树
  • 优化
  • codegen

首先解析模板,生成AST语法树(一种用JavaScript对象的形式来描述整个模板)。

使用大量的正则表达式对模板进行解析,遇到标签,文本的时候都会执行对于的钩子进行相关处理。

Vue的数据是响应式的,但其实模板中并不是所有的数据都是响应式的。有些数据首次渲染后就不会再变化。那么优化过程就是深度遍历AST树,按照相关条件对树节点进行标记。这些被标记的节点(静态节点)我们就可以跳过对他们的对比,对运行时的模板起到很大的优化作用。

编译的最后一步是将优化后的AST树转换为可执行的代码。


十.Vue的数据为什么频繁变化但只会更新一次?

这是因为vue的Dom更新是一个异步操作,在数据更新后会首先被set钩子函数监听到,但是不会马上执行DOM更新,而是在下一轮循环中执行更新。

具体实现是vue中实现了一个queue队列用于存放本次事件循环中的所有watcher更新,并且同一个watcher的更新只会被推入队列一次,并在本轮事件循环的微任务执行结束后执行此更新,这就是DOM只会更新一次的原因。

这种在缓冲时去除重复数据对于避免不必要的计算和dom操作是非常重要的。然后,在下一个的事件循环“tick”中,vue刷新队列并执行实际工作。vue在内部对异步队列尝试使用原生Promise.then,MutationObserve和setImmediate,如果执行环境不支持,则会采用setTimeout(fn,0)代替

文章来源:https://blog.csdn.net/weixin_63267832/article/details/135105476
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。