当前位置: 首页 > Web前端 > vue.js

vue高频原理面试篇+详细解答

时间:2023-03-31 21:34:15 vue.js

原文章首地址掘金三联哦更多好文章github大家好,我是林依依,这是一道关于vue原理的面试题,如果可以的话完全理解了,相信对大家很有帮助。面试题1.对MPA/SPA的理解有什么优势和劣势?MPA多页应用程序。构成:多页html构成,跳转方式:页面跳转是从一个页面刷新到另一个页面:整页刷新页面数据跳转:依赖URL/cookie/localStorage跳转后的资源会重新加载加载优点:对SEO更友好,开发难度较低。SPA单页应用页面构成:由shell页面包裹,由多个页面(组件)片段组成跳转方式:在shell页面中跳转,显示或隐藏片段页面(组件)刷新方式:局部页面刷新页面数据跳转:更容易在组件之间传递值。跳转后的资源不会重新加载。缺点:对SEO搜索不是很友好,需要单独配置。开发难度较大,需要专门的开发框架。iframe其实就是MPA,但是可以达到SPA的一些效果,但是本身存在很多问题。2.俗话说,为什么我们需要这些MVC/MVVM模式?谈谈您在MVC和MVVM模式之间的区别。目的是学习后端思想,职责分离和分层Vue。React不是真正意义上的MVVM,更不是MVC。两者的核心只处理视图层视图。MVC模式下的单向数据,用户的每一步操作都需要重新请求数据库修改视图层的渲染,形成单向闭环。比如jQuery+underscore+backbone。M:模型数据存储层V:view:页面视图层C:controller:控制器js逻辑层。controller控制层处理data层model层的数据,显示在view层view层。同样,视图层视图层接收用户指令,也可以通过控制层控制器作用于数据层模型。所以MVC的缺点就是视图层不能直接和数据层交互。MVVM模式隐藏了controller控制层,直接操作View视图层和Model数据层。M:model数据modelV:view视图模板VM:view-model视图数据模板(vue处理的层,vue中definedProperty是处理VM层的逻辑)双向数据绑定:model数据model层绑定Data通过dataBindings直接影响视图层View,而视图层view也可以通过监听DomListener改变数据模型层model。数据绑定和DOM事件监听是Vue在viewModel层主要做的事情。也就是说:只要将数据模型层Model的数据挂载到ViewModel层Vue,就可以实现双向数据绑定。再加上vuex/redux可以作为vue和react的模型数据层。varvm=newVue()vm是view-model数据模型层,data:是vmview-model层表示的数据。总结一下两者的区别:MVC的视图层和数据层的交互需要通过控制层控制器进行单向链接。MVVM隐藏了控制层的controller,让视图层和数据层可以直接交互,是一种双向连接。3.说说理解Vue中响应式数据的一个小技巧:响应式数据就是说数据发生了变化,视图可以因为响应式数据而更新。Vue中实现了一个definedReactive方法,方法内部借用了Object.definedProperty()为每个属性添加了get/set属性。definedReactive只能监控最外层的对象,递归劫持内部对象的数据。数组改写为7pushpopshiftunshiftreversesort拼接为数组截取数据,因为这些方法会改变原来的数组扩展://src\core\observer\index.jsexportfunctiondefineReactive(obj:Object,key:string,val:any,customSetter?:?Function,shallow?:boolean){//准备给属性添加一个dep依赖集合Watcher更新视图。constdep=newDep()//somecode//observe()用于观察值的类型,如果是属性和对象,递归,为每个属性添加`get/set`letchildOb=!shallow&&observe(val)Object.defineProperty(obj,key,{enumerable:true,configurable:true,get:functionreactiveGetter(){//这里取数据时依赖于集合constvalue=getter?getter.call(obj):valif(Dep.target){dep.depend()//childOb收集对象的依赖if(childOb){childOb.dep.depend()//这里递归收集数组和内部数组的依赖,这里是key的thearrayvalue和value都有依赖if(Array.isArray(value)){dependArray(value)}}}returnvalue},set:functionreactiveSetter(newVal){//当属性改变时,会通知watcher在这里更新视图}})}上面的Dep(class)是做什么用的?答:Watcher用来采集效果图,什么是Watcher?答:watcher是一个用来更新视图的类4.Vue如何检测数组的变化?Vue并没有使用definedProperty()对数组的每一项进行数据拦截,而是重写了数组的方法pushpopshiftunshiftreversesortsplice。手动调用notify通知renderwatcher,如果执行更新数组中有对象类型(对象和数组),就会进行数据拦截。所以不会通过修改数组下标和数组长度来进行数据拦截,不会有响应式的变化。例如arr[0]=1,arr.length=2不会有响应式展开://src\core\observer\array.jsconstmethodsToPatch=['push','pop','shift','unshift','splice','sort','reverse']methodsToPatch.forEach(function(method){constoriginal=arrayProto[method]def(arrayMethods,method,functionmutator(...args){constresult=original.apply(this,args)constob=this.__ob__letinsertedswitch(method){case'push':case'unshift':inserted=argsbreakcase'splice':inserted=args.slice(2)break}//新的再次观察增加的类型if(inserted)ob.observeArray(inserted)//手动调用notify派发更新ob.dep.notify()returnresult})})5.Vue如何依赖集合?(dep和Watcher是什么关系)提示:Dep是负责收集Watcher的类,Watcher是封装渲染视图逻辑的类,用于调度更新。需要注意的是,Watcher不能直接更新视图,需要结合Vnode在patch()中通过diff算法生成真正的DOM。每个属性都有自己的dep属性来存储依赖的Watcher。属性发生变化后,会通知Watcher进行更新。当用户获取(getter)数据时,Vue为每个属性添加一个dep属性,以(collectasDependency)收集Watcher。dep.notify()在用户设置属性值时通知收集到的Watcher重新渲染。有关详细信息,请参阅上面的defineReactive()。Dep取决于集合类。它与Watcher类是多对多的双向存储关系。每个属性可以有多个Watcher类,因为属性可能在不同的组件中使用。同时一个Watcher类也可以对应多个属性。6、Vue中的模板编译360px"/>Vue中的模板编译:其实就是把模板转换成render函数。说白了,第一步就是将真实DOM(模板)编译成虚拟dom(Vnode)。第一步是将模板模板字符串转换成ast语法树(parser解析器)。这里使用了大量正则规则来匹配标签和属性的名称。,text等。第二步静态标记AST的静态节点,主要用于虚拟DOM渲染优化(optimizeoptimizer)。这里会遍历所有的子节点,并进行静态标记。第三步,使用AST语法树重新生成renderFunction代码字符串代码。(codeGen代码生成器)为什么要静态标记节点?如果是静态节点(没有绑定数据,前后不需要变化的节点),那么就不需要diff算法进行比较。7、生命周期钩子的实现原理Vue中的生命周期钩子只是一个回调函数,在创建组件实例化的过程中会调用相应的钩子执行。使用Vue.mixin({})在钩子或生命周期中定义多个函数。Vue会在内部调用mergeHook()合并钩子,放入队列依次执行扩展//src\core\util\options.jsfunctionmergeHook(parentVal:?Array,childVal:?Function|?Array):?Array{constres=childVal?父母价值?parentVal.concat(childVal)//合并:Array.isArray(childVal)?childVal:[childVal]:parentValreturnres?dedupeHooks(res):res}8.commonplace的vue生命周期是怎样的,请求通常发送到哪里?beforeCreate:刚开始初始化vue实例,在数据观察observer之前调用,数据/方法等属性还没有创建created:vue实例初始化完成,所有属性都已经创建。beforeMount:这个钩子在vue在页面挂载数据之前触发,此时触发render函数。mounted:el被创建的vm.$el替换,vue初始化的数据已经挂载到页面上,真正的DOM可以在这里访问。这里一般要求数据。beforeUpdate:在数据更新时调用,也就是在虚拟dom重新渲染之前调用。updated:发生在数据变化导致虚拟dom重新渲染之后。beforeDestroy:这个钩子在实例被销毁前调用,实例还在。vm.$destroy触发两个方法。destroyed:在Vue实例被销毁后调用。将联系所有事件侦听器。请求数据根据具体的业务需求决定发送到哪里使用场景和原理ajax9.Vue.mixin({})使用场景:用于抽取一个通用的业务逻辑实现复用。实现原理:调用mergeOptions()方法使用策略模式合并不同的属性。如果混入的数据与组件的数据有冲突,则使用组件本身。Vue.mixin({})的缺陷,1.可能会导致mixed-in属性名和组件属性名的命名冲突;2.源数据依赖extendsexportfunctionmergeOptions(parent:Object,child:Object,vm?:Component):Object{//somecodeif(!child._base){if(child.extends){parent=mergeOptions(parent,child.extends,vm)}if(child.mixins){for(leti=0,l=child.mixins.length;i