2023前端面试笔记

生命周期

生命周期钩子是如何实现的
生命周期钩子就是回调函数而已,当创建组件实例的过程中会调用的钩子方法
补充:
内部主要是使用callhook方法来调用对应的方法,核心是一个发布订阅模式,将钩子订阅好(内部采用数组的方式存储),在对应阶段进行发布

1. 什么是生命周期
vue实例从创建到销毁的一个过程。就是开始创建、初始化数据编译模板,挂载DOM渲染、更新、卸载等一系列的过程
2. 生命周期的作用
生命周期中会有很多的事件钩子,可以让我们更好的控制vue的实例化过程,从而形成更好的逻辑
3. 生命周期有几个阶段
八个阶段。初始化前/后、载入前/后、更新前/后、销毁前/后
beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed
4. 第一次加载会触发哪几个钩子
beforecreate、created、beforemount、mounted
5. DOM渲染在哪个周期完成
mounted 中就已经完成

v-show 与 vi-if 的区别
v-show 是css的切换 频繁切换用vshow
v-if是dom的创建与销毁
开发中常用的指令
v-if、v-show、v-on、v-model、v-for

组件之间的通信

1. 父组件给子组件传值
父组件可以使用props像子组件传值
2. 子组件给父组件通信
子组件通过$emit触发事件,回调给父组件

3. 非父子、兄弟组件之间通信
可以通过引入bus作为媒介,然后分别通过调用bus事件触发和监听来实现通信和参数的传递
EventBus
这种方法通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件。

还可以使用ref与 $parent / $children 访问
ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例

vuex也可以用来组件之间的通信

组件中写name选项有哪些好处及作用

  1. 可以通过名字找到对应的组件(递归组件)
  2. 可以通过name属性实现缓存功能(keep-alive)
  3. 可以通过name来识别组件(跨组件通信时非常重要)

keep-alive平时在哪里使用?原理

keep-alive主要时组件缓存,采用的时LRU算法。最近最久未使用法。
常用的两个属性include/exclude,允许组件有条件的进行缓存。
两个生命周期activated/deactivated,用来得知当前组件是否处于活跃状态。

abstract: true, // 抽象组件

Vue.minxin的使用场景和原理?

Vue.mixin的作用就是抽离公共的业务逻辑,原理类似“对象的继承”,当组件初始化时会调用 mergeOptions方法进行合并,采用策略模式针对不同的属性进行合并,如果混入的数据和本身组件中的数据冲突,会采用“就近原则”以组件的数据为准。

补充回答:

mixin中有很多缺陷“命名冲突问题”,“依赖问题”,“数据来源问题”,这里强调一下mixin的数据是不会被共享的。

MVVM

就是一个设计模式 数据与视图的一个双向绑定、可以通过数据改变视图、也可以通过视图改变数据
M model 代表 数据模型
V view 代表UI组件
VM viewmodel 监听模型数据的改变和控制视图的对象

key

key 是vue中vnode标记的唯一id 可以通过这个key,使diff操作更快、更准确
准确
如果不加key,那么vue会选着复用节点(vue的就地更新策略)导致之前节点的状态被保留下来,会产生一系列的bug
快速
key的唯一性可以被map数据结构充分利用

组件中的data为什么是函数?

因为组件是用来复用的,js里的对象是引用关系,这样作用域就没有被隔离,会影响所有的实例。为了保证组件不同实例之间的data不冲突,data必须是一个函数。而new vue 的实例是不会被复用的,因此不存在引用对象的问题

v-model 的原理

vue中主要使用v-model的指令在表单input、select、textarea等元素上创建双向数据绑定,v-model本质上是vue的语法糖。v-model内部为输入不同的元素使用不同的属性并抛出不同的事件

js

1. 防抖节流 应用场景
防抖就是多次执行变为一次执行 联想搜索
节流就是多次执行变为每隔一段时间执行 监听滚动事件、比如是否滑倒底部加载更多
2. 什么是闭包
闭包就是能够读取其他函数内部变量的函数
「函数」和「函数内部能访问到的变量」(也叫环境)的总和,就是一个闭包
3. 什么是深拷贝、浅拷贝,有哪些实现方式

promise和async await区别

  1. Promise和async都是异步的一个请求方式,且都是非阻塞的
  2. Async是基于promise去实现的 async是一个修饰符 被修饰的函数是一个异步函数 且await只能在async修饰的函数中使用
  3. Promise的书写方法是链式的 容易造成代码的堆叠 不易维护,而async的书写方法比较简洁 更像是同步代码比较好理解和维护
  4. Promise的返回时一个对象 需要用then catch去处理返回的数据和抛出的异常 而async使用的try catch去处理数据和异常
  5. Promise的返回可能在请求还没结束时就先执行了外面的操作
    而async的话是遇到await就会等待返回结果再执行后面的操作

$emit的底层
$emit有两个参数,第一个参数是字符串类型,就是需要回调事件的名称,第二个参数是需要传递的数据
$emit第一步会把第一个参数 字符串转换成小写并检查名称是否符合语法标准,然后会去事件列表中找对应的回调函数,如果没有找到会直接返回,如果找到了会进行一次判断,判断回调函数是否大于一,如果大于一就转换成数组。
这时候第一个参数就不重要了,emit会舍弃第一个参数。然后把第二个参数数据转换成数组,传递给一个带try,catch的invokeWithErrorHandling()方法,在其中使用apply()或call()来调用回调函数

css

1. 怎么实现元素的水平垂直居中
2. 什么是盒子模型
3. 什么是BFC模式
4. css提高性能的方法

  1. 异步加载css
  2. 资源压缩
  3. 合理使用选择器
  4. 不要使用@import
  5. 减少使用昂贵的属性

数据类型有哪几种?ES新增的数据类型

基础数据类型有 string Boolean number undefined null
引用类型 object array function
es6 新增的数据类型 symbol se10新增 bigint

项目中用过哪些ES6?

const let ()=> foreach …

v-if和v-for一起使用的弊端以及解决办法

因为v-for比v-if优先级高,如果遍历的数组元素个数比较多,但是满足v-if条件比较少的情况下,会浪费性能,建议不要使用。

而且,每次刷新页面时,都会执行这样性能不高的代码。

如果需要相应的逻辑, 可以用计算属性computed解决,通过数组方法filter过滤数组,v-for直接循环计算属性的结果,就不需要使用v-if了。

而且computed是有缓存的,就是在它的依赖没有变化时,不会再执行对应计算属性的函数,就提高了性能。

如果v-if在v-for外层的话,可以使用template标签。

vue性能优化

尽量使用v-if代替v-show
减少data中的数据,因为data中的数据是双向绑定,会为每一个数据增加getter和setter
保证key的唯一性
图片懒加载
第三方模块按需导入
路由使用懒加载、异步组件

vue双向绑定的原理?vue3做了哪些优化?怎么进行DIFF算法的?

通过数据劫持结合发布者-订阅者模式的方式,通过“Object.defineProperty()”放来来劫持各个属性的 getter、setter,在消息变动时发布给相应的订阅者来触发回调
vue3中是使用了proxy方法来劫持数据
proxy的优点是

  1. 可以直接监听对象而非属性
  2. 可以直接监听数据的变化,而vue2中监听数组时是重写了数组的方法,splice、push、pop、shift、unshift、等7个方法
  3. 有更多的拦截方式
  4. proxy返回的是一个新的对象,我们只要操作新的对象就可以达到目的,而Object.defineProperty 只能去遍历对象的属性进行修改

nextTick在哪里使用?原理是?

核心答案:

nextTick的回调是在下次DOM更新循环结束之后执行的延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM。nextTick主要使用了宏任务和微任务。原理就是异步方法(promise, mutationObserver, setImmediate, setTimeout)经常与事件循环一起来问。

补充回答:

vue多次更新数据,最终会进行批处理更新。内部调用的就是nextTick实现了延迟更新,用户自定义的nextTick中的回调会被延迟到更新完成后调用,从而可以获取更新后的DOM。

Vue 为什么需要虚拟DOM? 虚拟DOM的优劣如何?

核心答案:

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

补充回答:

虚拟DOM的实现就是普通对象包含tag、data、children等属性对真实节点的描述。(本质上就是在JS和DOM之间的一个缓存)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Vue 中的diff原理

核心答案:

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

补充回答:

  1. 先比较是否是相同节点

  2. 相同节点比较属性,并复用老节点

  3. 比较儿子节点,考虑老节点和新节点儿子的情况

  4. 优化比较:头头、尾尾、头尾、尾头

  5. 比对查找进行复用

Vue2 与 Vue3.x 的diff算法:

Vue2的核心Diff算法采用了双端比较的算法,同时从新旧children的两端开始进行比较,借助key值找到可复用的节点,再进行相关操作。

Vue3.x借鉴了ivi算法和 inferno算法,该算法中还运用了动态规划的思想求解最长递归子序列。(实际的实现可以结合Vue3.x源码看。)

computed 和 watch 的区别和运用的场景?

核心答案:

computed: 计算属性。依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;

watch: 监听数据的变化。更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;

运用场景:

1)当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;

2)当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

Vue性能优化

1、你都做过哪些Vue的性能优化?( 统计后的结果 )

1)编码阶段

尽量减少data中的数据,data中的数据都会增加getter和setter,会收集对应的watcher;

如果需要使用v-for给每项元素绑定事件时使用事件代理;

SPA 页面采用keep-alive缓存组件;

在更多的情况下,使用v-if替代v-show;

key保证唯一;

使用路由懒加载、异步组件;

防抖、节流;

第三方模块按需导入;

长列表滚动到可视区域动态加载;

图片懒加载;

2)用户体验:

骨架屏;

PWA;

还可以使用缓存(客户端缓存、服务端缓存)优化、服务端开启gzip压缩等。

3)SEO优化

预渲染;

服务端渲染SSR;

4)打包优化

压缩代码;

Tree Shaking/Scope Hoisting;

使用cdn加载第三方模块;

多线程打包happypack;

splitChunks抽离公共文件;

sourceMap优化;

vuex的使用?实现原理

SPA 单页面的理解、优缺点是啥

new Vue() 发生了什么?

Vue.use是干什么的?原理是什么?

请说一下响应式数据的理解?

Vue如何检测数组变化?Vue如何检测数组变化?

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

Vue中模板编译原理?

Proxy 与 Object.defineProperty 优劣对比

Vue3.x响应式数据原理

Vue-router有几种钩子函数?具体是什么及执行流程是怎样的?

nextTick在哪里使用?原理是?

Vue 为什么需要虚拟DOM? 虚拟DOM的优劣如何?

Vue 中的diff原理

猜你喜欢

转载自blog.csdn.net/double_Fly_/article/details/129005922
今日推荐