面试复盘-叮咚买菜

这不是第一次面大厂了,第一次面的扇贝,面试过程有点紧张,结束后回想不起啦更多内容…
以后每次大厂面试完都要记得复盘下,复盘的过程也是查漏补缺的过程,希望可以早日进入大厂,早日突破20k大关

开胃菜

刚开始面试,双方都是不怎么熟悉的状态,一般都会让进行自我介绍,参考了知乎、掘金后,总结了一个自我介绍的范文。

1
2
3
4
我叫xxx, xxx年毕业于xxx学校,xxxx专业,本科;
目前从事开发岗位已经x年,期间独立完成多个项目,主要用到的技术有巴拉巴拉
当前这份工作的工作内容
希望能得到贵公司大平台的学习与工作交流机会,去实现不一样的人生价值(升华一下)

技术回顾

vue的生命周期&每个生命周期执行了哪些操作

生命周期 说明
beforeCreate 在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
created 创建vue实例并初始化。在这一步,实例已完成以下的配置:数据观测 (data observer), 属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
beforeMount 在挂载开始之前被调用:相关的 render 函数首次被调用。
mounted 挂载dom之后调用,把解析后的模板与页面元素进行绑定,用解析后的模板内容替换页面
beforeUpdate 数据更新时调用
updated 数据更新后调用
activated keep-alive 组件激活时调用
deactivated keep-alive 组件停用时调用
beforeDestroy 实例销毁之前调用。在这一步,实例仍然完全可用
destroyed Vue 实例销毁后调用
errorCaptured 当捕获一个来自子孙组件的错误时被调用

一般在vue的哪个生命周期进行接口请求,为什么

不考虑服务器端渲染,一般选在 mounted 周期内请求数据,因为这个周期开始时,当前组件已经被挂载到真实的元素上了。
若是从服务器端渲染的话,在created 周期内

destroyed这个阶段执行了哪些操作

首先触发我们自己编写的beforeDestroy生命周期函数
然后递归清除vnode子节点,接着清除watchers所有对应的依赖
最后再清除相关节点的引用就结束了
更详细查看刁钻面试官:vue 节点销毁的时候做了些什么?

v-model语法糖的实现

动态绑定了 input 的 value 指向了 messgae 变量,并且在触发 input 事件的时候去动态把 message 设置为目标值

1
2
3
<input v-model="sth" />
// 等同于
<input v-bind:value="message" @input="message=$event.target.value">

vue双向绑定原理

Vue双向绑定原理是采用发布订阅者模式,在初始化时劫持数据的各个属性的setter/getter,在数据变动时发布消息给订阅者,触发响应的监听回调。

vue2

vue2中使用的Object.defineProperty对于数据进行拦截,其实还是有缺陷的

  1. 对象属性的新加或者删除无法监听(vue2解决方案深度遍历)
  2. 数组元素的增加和删除无法监听(为了解决这个问题,Vue对数组的方法进行了重写)
1
2
3
4
5
6
// 重写push
let oldPush = Array.prototype.push
Array.prototype.push = function() {
console.log('这里触发view更新')
oldPush.call(this,...arguments)
}
vue3

针对Object.defineProperty的缺点,ES6 Proxy都能够完美得解决,它唯一的缺 点就是,对IE不友好,所以vue3在检测到如果是使用IE的情况下(没错,IE11都不支持Proxy),会自动降级为Object.defineProperty的数据监听系统。

什么是深拷贝&浅拷贝

定义

实现

vue中更新了数据后获取最新dom对象

vue中数据是同步更新的,不过更新dom是异步的,所以需要更新数据后获取最新dom,需要使用nextTick获取最新的DOM

vue路由懒加载的实现

懒加载定义:把不同路由对应的组件分割成不同的代码块,然后当路由被访问时才加载对应的组件即为路由的懒加载,可以加快项目的加载速度,提高效率

vue异步组件
es6的import()

修改后的做法是定义了一个函数,由于函数不调用不执行,所有,一开始时,并不会引入该组件,只有路由跳转时才会调用该函数。

1
2
3
原来是:import ShopCar from '@/pages/ShopCar'

修改后:const ShopCar = () => import('@/pages/ShopCar');
webpack的require,ensure():

箭头函数和普通函数的区别

this

数箭头函数没有 prototype (原型),所以箭头函数本身没有this​​​​​​​,它只会从自己的作用域链的上一层继承this。
普通函数this指向直接调用者,没有直接调用者,this指向window

ps:.call()/.apply()/.bind()无法改变箭头函数中this的指向

箭头函数没有自己的arguments
箭头函数不能作为构造函数使用

箭头函数没有自己的this,它的this其实是继承了外层执行环境中的this,且this指向永远不会随在哪里调用、被谁调用而改变,所以箭头函数不能作为构造函数使用,或者说构造函数不能定义成箭头函数,否则用new调用时会报错!

前端如何实现分页组件

思路:一次性将数据获取,将需要的部分显示,不需要的部分隐藏

  1. 计算出一共分为几页
  2. 计算开始显示的行数,和最后显示的行数
  3. 遍历显示数据实现分页

实现图片懒加载

思路:将页面里所有img属性src属性用data-xx代替,当页面滚动直至此图片出现在可视区域时,用js取到该图片的data-xx的值赋给src。

getBoundingClientRect

Element.getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置

1
2
3
// 伪代码
// clientHeight 代表当前视口的高度
img.getBoundingClientRect().top < document.documentElement.clientHeight
IntersectionObserver

该方法能够监听元素是否到了当前视口的事件,一步到位!

1
2
3
4
5
6
7
8
9
10
11
12
13
const observer = new IntersectionObserver((changes) => {
// changes: 目标元素集合
changes.forEach((change) => {
// intersectionRatio
if (change.isIntersecting) {
const img = change.target
img.src = img.dataset.src
observer.unobserve(img)
}
})
})

observer.observe(img)
LazyLoading属性
1
<img src="shanyue.jpg" loading="lazy">

对promise和await的理解

压箱底笔记:Promise和Async/await的理解和使用

事件捕获和事件冒泡区别

事件捕获:当你使用事件捕获时,父级元素先触发,子级元素后触发,即div先触发,p后触发。
事件冒泡:当你使用事件冒泡时,子级元素先触发,父级元素后触发,即p先触发,div后触发。

怎么阻止捕获和冒泡

阻止事件冒泡

事件的对象有的stopPropagation()方法

阻止事件捕获

stopPropagation和stopImmediatePropagation

这两方法区别:stopPropagation只会阻止冒泡或者是捕获,但是stopImmediatePropagation除此之外还会阻止该元素的其他事件发生

用解构赋值的方法取数组最后一位

1
2
3
let arr = [1, 2, 3, 4, 5];
let [last, ...rest] = [...arr].reverse();
console.log(last) // 5

正则表达式取0-10的数字

^([1-9]|10)$

vue异步加载组件的方法

异步组件的核心可以给组件定义变成一个函数,函数里面可以用import语法,实现文件的分割加载,import语法是webpack提供的,采用的就是jsonp。


面试复盘-叮咚买菜
https://xypecho.github.io/2021/03/29/面试复盘-叮咚买菜/
作者
很青的青蛙
发布于
2021年3月29日
许可协议