Vue面试题,背就完事了

1. Vue中如何检测数组的变化?

vue中对数组没有进行defineProperty,而是重写了数组的7个方法。 分别是:

push
shift
pop
splice
unshift
sort
reverse
因为这些方法都会改变数组本身。

数组里的索引和长度是无法被监控的。

2. Vue中如何进行依赖收集的?

Vue初始化的时候,挂载之后会进行编译。生成renderFunction。

当取值的时候,就会搜集watcher,放到dep里面。

当用户更改值的时候,就会通知watcher,去更新视图。

3. 如何理解Vue中的模板编译原理?

这个问题的核心是如何将template转换成render函数。

将template模块转换成ast语法书 - parserHTML
对静态语法做标记(某些节点不改变)
重新生成代码 - codeGen,使用with语法包裹字符串

4. Vue组件生命周期有哪些?

beforeCreate 在实例初始化之后,数据观测observer 和event、watcher事件配置之前被调用
created 实例已经创建完成,在这一步,以下配置被完成
	数据观测
	属性和方法的运算
	watch/event事件回调
	$el尚未生成
beforeMount 在挂载之前被调用,render尚未被调用
mounted el被新创建的vm.$el替换,并挂载到实例上去之后调用
beforeUpdate 数据更新时,被调用,发生在虚拟Dom重新渲染和打补丁之前
update 由于数据更改导致的虚拟Dom重新渲染和打补丁,在这之后调用
beforeDestroy 实例销毁之前调用
destroyed 实例销毁之后调用,调用后Vue实例的所有东西都会被解绑,所有的事件监听会被移除,子实例被销毁,该钩子在服务端渲染期间不被调用
keep-alive(activated & deactivated)

5. Vue的组件data为什么必须是一个函数?

new Vue是一个单例模式,不会有任何的合并操作,所以根实例不必校验data一定是一个函数。
组件的data必须是一个函数,是为了防止两个组件的数据产生污染。
如果都是对象的话,会在合并的时候,指向同一个地址。
而如果是函数的时候,合并的时候调用,会产生两个空间。

6. 请说明nextTick的原理。

nextTick是一个微任务。

nextTick中的回调是在下次Dom更新循环结束之后执行的延迟回调
可以用于获取更新后的Dom
Vue中的数据更新是异步的,使用nextTick可以保证用户定义的逻辑在更新之后执行

7. computed和watch的区别是什么?

computed和watch都基于watcher来实现的。
computed的属性是具备缓存的,依赖的值不发生变化,对其取值时计算属性方法不会重复执行
watch是监控值的变化,当值发生改变的时候,会调用回调函数

8. Vue.set方法是如何实现的?

vue给对象和数组本身都增加了dep属性
当给对象新增不存在的属性的时候,就会触发对象依赖的watcher去更新
当修改数组索引的时候,就调用数组本身的splice方法去更新数组

9. Vue为什么要用虚拟Dom?

虚拟dom就是用js对象来描述真实Dom,是对真实Dom的抽象
由于直接操作Dom性能低,但是js层的操作效率高,可以将Dom操作转化成对象操作。最终通过diff算法比对差异进行更新Dom
虚拟Dom不依赖真实平台环境,可以实现跨平台

10. Vue的diff算法原理是什么?

Vue的diff算法是平级比较,不考虑跨级比较的情况。内部采用深度递归的方式+双指针方式比较

先比较两个节点是不是相同节点
相同节点比较属性,复用老节点
先比较儿子节点,考虑老节点和新节点儿子的情况
优化比较:头头、尾尾、头尾、尾头
比对查找,进行复用

11. 既然vue通过数据劫持可以精准的探测数据变化,为什么还要进行diff检测差异?

响应式数据变化,Vue确实可以在数据变化的时候,响应式系统可以立刻得知。但是如何每个属性都添加watcher的话,性能会非常的差。
粒度过细,会导致更新不精准
所以采用watcher + Diff算法来检测差异。

12. 请说明key的作用和原理

Vue在patch过程中,通过key可以判断两个虚拟节点是否是相同节点。
没有key会导致更新的时候出问题
尽量不要采用索引作为key

13. 谈谈对组件的理解

组件化开发能大幅提高应用开发效率、测试性、复用性
常用的组件化技术:属性、自定义事件、插槽
降低更新范围,值重新渲染变化的组件
高内聚、低耦合、单向数据流

14. 请描述组件的渲染流程

产生组件虚拟节点 -> 创建组件的真实节点 -> 插入到页面

15. 异步组件原理

先渲染异步占位符节点 -> 组件加载完毕后调用forceUpdate强制更新。

16. 函数组件的优势和原理

函数式组件的特性:无状态、无生命周期、无this。因此性能会高一点。
正常的一个组件是一个类继承了Vue。

函数式组件,就是一个普通的函数。

17. 组件的传值方式有哪些?

props和emit:父组件向子组件传递数据,通过prop传递。子组件传递数据给父组件是通过emit事件
parent,children获取当前组件的父组件和当前组件的子组件
attrs和listeners 。
父组件通过provide提供,子组件通过inject注入变量
$ref获取实例
eventBus平级组件数据传递
Vuex

18. $attrs是为了解决什么问题出现的?

主要作用是为了实现批量传递数据。

provide/inject更适合应用在插件中,主要实现跨级数据传递。

19. v-for和v-if哪个优先级更高?

首先,v-for和v-if 不能在同一个标签中使用。

先处理v-for,再处理v-if。

如果同时遇到的时候,应该考虑先用计算属性处理数据,在进行v-for,可以减少循环次数。

20. Vue的普通Slot以及作用域Slot的区别

普通插槽
普通插槽是渲染后做替换的工作。父组件渲染完毕后,替换子组件的内容。

作用域插槽
作用域插槽可以拿到子组件里面的属性。在子组件中传入属性然后渲染。

21. Vue.use是干什么的?

Vue.use是用来使用插件的。我们可以在插件中扩展全局组件、指令、原型方法等。 
会调用install方法将Vue的构建函数默认传入,在插件中可以使用vue,无需依赖vue库

22. vue的修饰符有哪些?

.stop
.prevent
.capture
.self
.once
.passive
.right
.center
.middle
.alt

23. keep-alive平时在哪里使用?原理是什么?

使用keep-alive包裹动态组件时,会对组件进行缓存,避免组件重新创建
使用有两个场景,一个是动态组件,一个是router-view

include 字符串或正则表达式。只有名称匹配的组件会被缓存
exclude 字符串或正则表达式。任何名称匹配的组件都不会被缓存
max 数字、最多可以缓存多少组件实例

24. vue-router有几种钩子函数?执行流程如何?

钩子函数有三种:

全局守卫
路由守卫
组件守卫

25. 谈谈Vue的性能优化有哪些?

编码阶段
尽量减少data中的数据,data中的数据都会增加getter和setter,会收集对应的watcher
v-if和v-for不能连用
如果需要使用v-for给每项元素绑定事件时使用事件代理
SPA 页面采用keep-alive缓存组件
在更多的情况下,使用v-if替代v-show
key保证唯一
使用路由懒加载、异步组件
防抖、节流
第三方模块按需导入
长列表滚动到可视区域动态加载
图片懒加载
SEO优化
预渲染
服务端渲染SSR
打包优化
压缩代码
Tree Shaking/Scope Hoisting
使用cdn加载第三方模块
多线程打包happypack
splitChunks抽离公共文件
sourceMap优化
用户体验
骨架屏
PWA
还可以使用缓存(客户端缓存、服务端缓存)优化、服务端开启gzip压缩等。

数据层级不要过深,合理的设置响应式数据
使用数据时,缓存值的结果,不频繁取值
合理设置key
v-show(频繁切换性能高)和v-if的合理使用
控制组件的粒度 -> Vue采用组件级别更新
采用函数式组件 -> 函数式组价开销低
采用异步组件 -> 借助webpack的分包策略
使用keep-alive来缓存组件
虚拟滚动、时间分片等策略
打包优化

26. 谈谈你对Vuex的理解?

Vuex是专门为vue提供的全局状态管理系统,用于多个组件中的数据共享、数据缓存。
state(单一状态树) getter/Mutation显示提交更改state
Action类似Mutation,提交Mutation,可以包含任意异步操作。
module(当应用变得庞大复杂,拆分store为具体的module模块)

问题:无法持久化。

27. 双向绑定实现原理

当一个Vue实例创建时,Vue会遍历data选项的属性,用 Object.defineProperty 将它们转为 getter/setter并且在内部追踪相关依赖,在属性被访问和修改时通知变化。每个组件实例都有相应的 watcher 程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher重新计算,从而致使它关联的组件得以更新。

28. v-model的实现以及它的实现原理吗?

vue中双向绑定是一个指令v-model,可以绑定一个动态值到视图,同时视图中变化能改变该值。v-model是语法糖,默认情况下相于:value和@input。
使用v-model可以减少大量繁琐的事件处理代码,提高开发效率,代码可读性也更好
通常在表单项上使用v-model
原生的表单项可以直接使用v-model,自定义组件上如果要使用它需要在组件内绑定value并处理输入事件
我做过测试,输出包含v-model模板的组件渲染函数,发现它会被转换为value属性的绑定以及一个事件监听,事件回调函数中会做相应变量更新操作,这说明神奇魔法实际上是vue的编译器完成的。

29. 你知道Vue3有哪些新特性吗?它们会带来什么影响?

性能提升
更小巧、更快速
支持自定义渲染器
支持摇树优化:一种在打包时去除无用代码的优化手段
支持Fragments和跨组件渲染

API变动
模板语法99%保持不变
原生支持基于class的组件,并且无需借助任何编译及各种stage阶段的特性
在设计时也考虑TypeScript的类型推断特性
重写虚拟DOM可以期待更多的编译时提示来减少运行时的开销
优化插槽生成可以单独渲染父组件和子组件
静态树提升降低渲染成本
基于Proxy的观察者机制节省内存开销

不兼容IE11
检测机制更加全面、精准、高效,更具可调试式的响应跟踪

30. 实现双向绑定 Proxy 与 Object.defineProperty 相比优劣如何?

Object.definedProperty的作用是劫持一个对象的属性,劫持属性的getter和setter方法,在对象的属性发生变化时进行特定的操作。而   Proxy劫持的是整个对象。
Proxy会返回一个代理对象,我们只需要操作新对象即可,而Object.defineProperty只能遍历对象属性直接修改。
Object.definedProperty不支持数组,更准确的说是不支持数组的各种API,因为如果仅仅考虑arry[i] = value 这种情况,是可以劫持   的,但是这种劫持意义不大。而Proxy可以支持数组的各种API。
尽管Object.defineProperty有诸多缺陷,但是其兼容性要好于Proxy。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值