1、vue编译原理【将 template 转成 render 函数的过程。】
(1)原理
浏览器运行时会把 template 转化成 render 函数,webpack 则不需要,(因为 vue loader已转换完成)get数据收集是在render函数中执行的,每个computed函数都会生成一个watcher和data里的数据绑定,data 数据变化后watcher执行,(所以才有了缓存) ,每个组件都会生成一个渲染watcher,里面主要是做微任务部分,总之同步任务做数据收集,微任务做diff及dom渲染。
(2)详细:主要分3个流程
2、vue 双向绑定原理【另一种问法:响应式数据的原理/页面更新,vue底层是如何响应】
采用数据劫持结合发布者订阅模式,通过 Object.defineProperty() 来劫持各个属性的 getter、setter,在数据变动时发给订阅者,触发相应事件。
注)数据劫持(vue.js);发布者-订阅模式(backbone.js);脏值检查(angular.j
另一种回答:数据劫持 + 观察者模式
对象内部通过 defineReactive 方法,使用 Object.defineProperty 将属性进行劫持(只会劫持已存在的属性),数组则是通过重写数组来实现。当页面使用对应属性时,每个属性都拥有自己的 dep 属性,存在它所依赖的 watcher (依赖收集)get,当属性变化后会通知自己对应的 watcher 去更新(派发更新)set。
1、Object.defineProperty 数据劫持
2、使用 getter 收集依赖 ,setter 通知 watcher派发更新。
3、watcher 发布订阅模式。
2、$set 原理?
如果目标是数组,直接使用数组的 splice 方法触发相应式;
如果目标是对象,会先判读属性是否存在、对象是否是响应式,最终如果要对属性进行响应式处理,则是通过调用 defineReactive 方法进行响应式处理( defineReactive 方法就是 Vue 在初始化对象时,给对象属性采用 Object.defineProperty 动态添加 getter 和 setter 的功能所调用的方法)
3、nextTick 实现原理?
(1)nexTick 的作用:nextTick 中的回调是在下次 DOM 更新循环结束之后执行的延迟回调。
(2)使用场景:在修改数据之后立即使用这个方法,获取更新后的 DOM
(3)nextTick 实现原理:采用微任务优先的方式调用异步方法去执行 nextTick 包装的方法。
4、vue 事件绑定原理?
原生事件绑定是通过 addEventListener 绑定真实的元素,组件事件绑定是通过 on 实现的。
注)如果要在组件上使用原生事件,需要加.native修饰符,这样就相当于在父组件中把子组件当做普通的HTML标签,然后加上原生事件。on、$emit 是基于发布订阅模式的,维护一个事件中心,on的时候将事件按名称存在事件中心里,称之为订阅者,然后emit将对应的事件进行发布,去执行事件中心里的对应的监听器。
5、观察者模式和发布订阅者模式的区别?【发布 / 订阅模式和观察者模式的区别是什么?】
两者最大的区别:发布订阅者模式有一个调度中心,观察者模式每个被订阅的目标都会有一个被观察的对象;而发布订阅者模式则会有一个调度中心,取消了发布订阅者之间的依赖,在这个中心可以控制有些数据可以不传输给订阅者,可以增加权限等;
6、vue2 和 vue3 实现双向绑定的区别?【Object.defineProperty和Proxy的区别】
(0)vue3采用了 proxy 代理,和 vue 2 中Object.defineProxy 一样有两个属性:get/set。
(1)vue3中的proxy一次性给所有对象都添加set和get属性。Object.defineProxy 一次只能给一个对象添加属性。
(2)proxy 不兼容IE,Object.defineProperty 不兼容IE8以下的。
(3)proxy 调用递归时,Object.defineProperty 在一开始就全部递归。
(4)Proxy 使用上比Object.defineProperty 方便的多、性能也比他好。
(5)proxy 代理整个对象,Object.defineProperty 只能代理对象上的某个属性。
(6)数组新增/删除/属性时,proxy 可以监听,Object.defineProperty 不行。
(7)对象上定义新属性时,proxy 可以监听,Object.defineProperty 不行。
注)proxy: vue 3.x 版本以上使用的;语法:可以使用new来定义;或者使用Proxy.revocable 的静态方法。
Object.defineProperty: vue 2.x 版本使用的,把内部解析成 observer、Dep,使用watch 相联。
7、vue2和vue3的区别,做了哪些优化?
(1)vue2 和 vue3 定义变量的方法不一样
vue2:定义变量在data 中,方法写在 methods 中。
vue3:定义的变量和方法都在 setup 中。
(2)vue2 和 vue3 生命周期钩子函数不同
vue2 生命周期 vue3 生命周期 beforeCreate -> setup // 组件创建之前 created -> setup // 组件创建立之后 beforeMount -> onBeforeMount // 组件加载 DOM 之前 Mounted -> onMounted // 组件加载 DOM 之后 beforeUpdate -> onBeforeUpdate // 组件更新 DOM 之前 updated -> onUpdated // 组件更新 DOM 之后 // 3.0 使用之前需要引入 import { reactive, toRefs, onMounted, onBeforeMount, onBeforeUpdate, onUpdated, } from "vue";
(3)vue3 支持 ts 更好。但是 2.0 也支持
8、为什么Vue3用了Proxy性能更好呢?
Object.defineProperty 对对象自身做个性,proxy 在 Object 基础上加一层拦截,不修改原对象。2.0 监听不了数据变化,监听手段单一,只能监听set 和 get,Proxy 有10几种监听,必须把所有的属性添加 defineProperty ,Proxy整个对象都会进行拦截。
9、proxy 是什么?proxy的缺点是什么? proxy 为什么比Object.defineProperty快?
(1)定义:在目标对象之前设置的“拦截”,外界访问时,都需要通过这层拦截,因此提供了一种机制,可以对外界的访问过滤和改写。
(2)缺点:浏览器兼容性问题,不兼容IE。
(3)Proxy的优点如下:
1. Proxy可以直接监听对象而非属性;
2. Proxy可以直接监听数组的变化;
3. Pxory有多种(13种)拦截方法,不限于apply、ownKeys、deleteProperty、has等等 是Object.defineProperty不具备的;
4. Proxy返回的是一个新对象,我们可以只操作新的对象达到目的,而Object.defineProperty只能遍历对象属性直接修改;
5. Proxy作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利;
Object.defineProperty的优点如下:
1. 兼容性好,支持 IE9,而Proxy 的存在浏览器兼容性问题,而且无法用 polyfill 磨平,因此 Vue 的作者才声明需要等到下个大版本( 3.0 )才能用 Proxy 重写
10、vue 组件通讯方式?
(1)props 和 emit。父组件向子组件传递数据是通过props传递的,子组件传递给父组件是通过emit。
(2)parent和parent 和 parent和children 获取单签组件的父组件和当前组件的子组件。
(3)父组件中通过 provide 来提供变量,然后在子组件中通过 inject 来注入变量。
【官方不推荐在实际业务中适用,但是写组件库时很常用。】
(4)$refs 获取组件实例
(5)events Bus 兄弟组件传参,就是中央事件总线。
(6)vuex 状态管理
(7)attrs和attrs 和 attrs和listeners A -> B -> C。Vue2.4开始提供了attrs和attrs和attrs和listeners来解决这个问题。
11、首页为什么会白屏?如何优化白屏?
(1)什么是白屏?
现在很多页面使用模版渲染,在网速不好的情况下,会导致出现loading 或者空白页,这种就叫白屏。
(2)白屏出现的原因【根本原因:网速 & 静态资源】
(3)解决方法(如何避免)
12、谈谈单页面应用与多页面应用的区别
(1)单页面(SPA):
(2)多页面(MPA):
13、在vue项目中你有没有做性能方面的优化,怎么做的?
百分之八十的人都说会:js、css 这些,这些是都是必须要做的。
性能优化过程中我们更多的需要考虑DMS解析、服务器缓存、浏览器缓存这些点。
(1)gzip
前端项目基本都放在cdn上,gzip压缩是有必须的,能减少js文件大小两到三倍
参考加速度nginx:gzip和缓存【nginx配置:在你对应的域名下,添加配置,重启服务 】
(2)服务器缓存(nginx 缓存)
(3)浏览器缓存
(4)vue 中的 keep-alive
做大型项目的时候,有很多个router,在页面快速切换中,为了保证页面加载的效率,可以使用缓存机制,也可以使用 keep-alive 里面包着rourter-view。keep-alive 会缓存组件,方便快速切换。
是否需要重新同步数据在vue-router 的钩子函数中判断。
(5)promise 请求(优点:1、减少回调;2、串并行处理;3、代码优雅)
注)ES6在性能优化上可以使用promise、async/await 压缩请求时间
(6)预加载