资料来源视频:用vue想拿20k,面试题要这样答文章是在看完视频之后总结的笔记 这个视频我觉得他将的好是在于直接去解析vue的源码,从源码分析问题,简而易懂且有说服力。
总结:一共9节9个小知识点
1、v-if和v-for的比较 2、vue组件data函数形式 3、key的作用 4、diff算法 5、组件化 6、vue设计理念 7、MVC MVP 和MVVM 8、vue优化 9、vue3特性
1、v-if和v-for的那个优先级更高,如果两个同时出现,应该怎么优化得到更好的性能
先上结论:v-for优先于v-if被解析
经过评论区大佬指导 更改结论为:
2.x 当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。
3.x当 v-if 与 v-for 一起使用时,v-if 具有比 v-for 更高的优先级。
2、vue组件data为什么必须是个函数,而vue根实例则没有此限制?
先上结论:1、data必须是个函数是保证在多实例的时候,为了保护相互之间的状态不干扰,不污染。2、每次在创建根实例的时候,使用new的方式,全局的范围内只创建一个,不会创建多个,不会存在污染的问题,因此可以不使用函数
函数每次执行都会返回全新的data对象实例
测试代码如下:
数据初始化是在:src/core/instance/init.js文件中
每次在创建根实例的时候,使用new的方式,全局的范围内只创建一个,不会创建多个,不会存在污染的问题,因此可以不使用函数,
在多实例的时候,为了保护相互之间的状态不干扰,不污染。vue的根实例所以需要使用function函数
结论:
vue组件可能存在多个实例,如果使用对象心事定义data,则会导致他们共用一个data对象,那么状态变更将会影响所有的组件实例,这是不合理的;采用函数形式定义没在initData是会将其作为工厂函数返回全新data对象,有效规避多实例之间的状态污染问题,而在vue根实例创建过程中则不存在改限制,也是因为根实例只能有一个,不需要担心这种问题
3、key工作原理,说说对它的理解
源码中找答案:src/core/vdom/patch.js-updateChildren()
正常回答是:可以唯一确定一个dom元素,从而执行diff算法更高效
案例分析:执行2秒后在c的前面插入f
结论:
1、key的作用主要是为了高效的更新虚拟DOM,其原理是vue在patch过程中通过key可以精准的判断两个节点是否是同一个,从而避免频繁更新不同元素,使得整个patch过程更加高效,减少了dom的操作量,提高性能
2、如果不设置key可能在列表更新时引发一些隐藏的bug 比如说更新和不更新看不出来。
3、vue中在使用相同标签名元素的过渡切换是,也会用到key属性,其目的也是为了让vue可以区分他们,否则vue只会替换其内部属性而不会触发过渡效果。需要用key来作为唯一性的判断。
4、怎么理解vue中的diff算法
1、diff算法必要性:
结论:组件中存在多个data中key的使用,怎么确保key发生了变化,执行diff算法就可以比较新旧两次虚拟dom的比较,为了精确的知道
2、diff算法的执行方式
核心源码:586行开始
3、diff算法的高效性:
就是上面提到的updateChildern()
总结: 1、diff算法是虚拟DOM技术的必然产物:通过新旧虚拟DOM做对比(既diff),将变化的地方更新在真实DOM上,另外,也需要diff高效的执行对比过程,从而降低时间复杂度为O(n) 2、vue2.0x中为了降低watcher粒度,每个组件只有一个watcher与之对应,只有引入diff才能精确的找到发生变化的地方 3、vue中diff执行的时刻是组件实例执行更新函数时,它会对比与上一次渲染结果oldVnode和新的渲染结果,此过程称为patch 4、diff过程整体遵循深度优先,同层次比较的策略,两个节点之间比较会根据他们是否拥有子节点或者文本节点做不同操作,比较两组子节点是算法重点,首先假设头部节点可能相同做4次对比尝试,如果没有找到相同节点才按照通用的方式去进行遍历查找,查找结束再按情况处理剩下的节点,借助key通常可以非常精确找到相同节点,因此整个patch过程非常高效。
5、vue组件化的理解
总体回答思路:组件化定义,优点,使用场景和注意事项等方面展开称述,同时要强调vue组件化中一些特点
1、源码分析:组件定义
把一些独立的功能单独提出来,有独立的函数,方便复用
vue中常见的定义第一种是全局定义 第二种是单文件组件的定义
2、源码分析:组件化优点
源码:lifecycle.js-mountComponent() 组件化优点:维护性 测试性,复用性,从组件 Watcher,渲染函数中去分析 在执行组件的时候,每一个组件会对应一个watcher,组件边变化的时候只会调用组件里面的渲染函数,可以把经常发生数据变化的单独放一个组件中,后期只需要执行这一个函数,起到局部刷新的作用。
3、组件化的实现
构造函数:src/core/global-api/extend.js
实例化及挂载:src/core/vdom、patch.js-createElm()
6、vue设计原则的理解
vue的官网上写了定义和特点: vue是一个渐进式的javscript框架 易用,高效,灵活
根据这个两个点去回答 渐进式javascript框架:
跟其他大型框架不同的是,vue被设计为可以自底向上逐层应用。vue的核心库只关注视图层,不仅易于上手,还便于与第三方库活既有的项目整合,另一方面,当现代的工具链以及各种支持类库结合使用的时候。vue也完全能够为复杂的单页面提供驱动 核心库就是一些声明是的渲染,组件系统 只关注视图层 可以作为一个库在其他项目中去用,也能作为一个大型的框架去搭建项目,这就是渐进式 学习过程也是渐进式的,只学习模板语法,基础功能也能开发,后期才学习工程化,
易用性:
vue提供数据响应式,声明式模板语法和基于配置的组件系统等核心特性,这些使我们只需要关注应用的核心业务即可,只要会写js。html和css就能轻松编写vue应用
灵活性:
渐进式框架最大的优点就是灵活性,如果应用足够小,我们可能仅仅需要vue的核心特性就能去完成功能了,随着应用规模的不断扩大,我们才可能追歼引入路由,状态管理,vue-cli等库和工具,不管是应用体积还是学习难度都是一个逐渐增加的平和曲线
高效性:
超快的虚拟DOM和diff算法使我们的应用有最佳的性能表现, 追求更高效的过程还在继续,vue3中引入proxy对数据响应式的改进以及编译器中对于静态内容的改进都会让vue更加高效
7、MVC MVP 和MVVM的理解
答题思路:
涉及的知识点比较多,很难说清楚,说透,因为mvc MVp这些模式我们前端程序员自己都没用过,当时恰恰反应了这些年全从无到有,从有到优的变化过程,沿着这个思路来回答
web1.0时代
在web1.0时代 并没有前端的概念。开发用过web应用多数采用ASP.NET、java PHP 项目通常有多个aspx/jsp/hph的单文件去组成,每个文件都有html css js或者java代码
为了让开发更加便捷,代码易于维护,前后端职责清晰,出现吗MVC 开发模式和框架。前端展示模板的形式出现的典型的框架就是Spring Structs Hibernate (SSH)
web2.0时代
自从Gmail的出现 ajax技术开始出现。前后端职责就更加清晰了,因为前端可以通过ajax与后端进行整体的数据交互,因此,整体的架构图也变化成了:
存在问题: 缺乏可行的开发模式承载更复杂的业务需求,页面内容都糅杂在一起,一旦应用规模增加,就会导致难以维护,因此,前端的MVC也随之到来
前后端分离的架构演变:MVC MVP MVVMMVC
前端的MVC与后端类似,具备View,Controller和Model
Model:负责应用数据的保存。与后端数据进行同步
Contoller:负责业务逻辑,根据用户行为对Model数据进行修改
View:负责视图展示。将model中的数据可视化出来
模型:
MVP
MVP与mvc很接近 P指的是Persenter 理解为一个中间人,他负责view和model之间的数据流,防止view好emodel之间直接交流,
MVVM
总结: 1、这三者都是框架模式,他们的设计目标都是为了解决Model和View的耦合问题 2、MVC模式出现较早主要应用在后端,如Spring MVC ASP.NET MVC等,有点是分层清晰,缺点是数据流混乱,灵活性带来的维护问题 3.MVP模式在MVC的进化形式, Presenter作为中间层负责MV通讯,解决了两者的耦合问题,但p层过去臃肿会导致维护问题 4、MVVM模式在前端领域有广泛应用,他不仅解决了MV耦合问题,还同时解决了维护两者射影关系的大量繁杂代码和DOM操作,也就是说不用去挨个改变DOM操作了,在提高开发效率,可读性同时还保持了优越的性能表现
8、你了解哪些vue的性能优化方法
主要讨论vue层面的优化
1、路由懒加载:
2、keep-alive缓存页面
3、使用v-show复用DOM
4、v-for遍历避免同时使用v-if
计算属性提前把数组进行过滤
5、长列表性能优化
如果列表纯粹是显示数据 不会有改变 数据就不需要响应式
如果是大数据列表,可以采用虚拟滚动,只渲染少部分区域内容
6、事件销毁
vue组件销毁时,会自动解绑他的全部指令及事件监听器,但仅限于组件本身的事件
7、图片懒加载
对于图片过多的页面 为了加速页面的加载速度,所以很多时候我们需要将页面内未出现在可视区域内的图片不做加载,等到滚动到可视区域之后再去加载
8、第三方插件按需导入
像element-ui这样的第三方组件库可以按需映入避免体积太大
9、无状态组件标记为函数式组件
展示型组件 ,这样的话就没有实例 标记functional
10.子组件分割
11、变量本地化
12 、SSR
服务端渲染。
9 vue3.0的新特性
更快:
虚拟DOM重写优化slots的生成 静态树提升 静态属性提升基于Proxy的响应式系统
更小:
通过摇树优化核心库体积 静态节点标记出来 减少重写
更容易维护:
TypeScript+模块化
更加友好:
跨平台:编译器核心和运行核心与平台无关,使得vue更容易与任何平台(web Android IOS)一起使用
更容易使用:
改进的TypeScript支持,编辑器能提供强有力的类型检查和错误及警告 更好的调试支持 独立的响应式模块 CompositionAPI
重点提出几个方向来写:虚拟DOM重写期待更多的编译时提示来减少运行时的开销,使得有效代码来创建虚拟节点 组件快速路劲+单个调用+子节点类型检测 跳过不必要的条件分支 JS引擎更容易优化
优化slots生成vue3中可以单独重新渲染父级和子级 确保实例正确的跟踪依赖关系 避免不必要的父子组件重新渲染
静态树提升 (staticTree Hoisting)使用静态树提升,意味着vue3的编译器将能够检测到什么是静态的 然后将其提升,从而降低了渲染成本、 跳过修补整棵树,从而降低渲染成本 即使多次出现也能正常工作
静态属性提升使用静态属性的提升,vue3打补丁的时候将跳过这些属性不会改变的节点 孩子还需要继续改变
基于Proxy的数据响应式vue2.0使用的是Object.definfPropertyde getter 和setter vue3将使用ES6中的Proxy作为观察机制: 组件实例初始化速度提100% 使用Proxy节省以前一半的内存太小,就爱快速度,但存在低浏览器版本不兼容,为了继续支持IE11 vue3将发布一个就观察者机制 和新的Proxy版本构建
高可维护性vue3将带来更可维护性的源代码,不仅使用Typescript 而且还许多包被解耦 更加模块化
作者:十九万里