当前位置: 首页 > Web前端 > HTML

vue高频面试题合集(三)附答案

时间:2023-03-27 23:25:41 HTML

为什么在Vue3.0中使用了Proxy而舍弃了Object.defineProperty?Object.defineProperty本身有一定的监听数组下标变化的能力,但是在Vue中,在性能/体验性价比上,有大放弃了这个特性。为了解决这个问题,可以使用如下方法监听数组push();pop();shift();unshift();splice();sort();reverse();只有以上7种方法被hack,所以其他阵法的属性也是检测不到的,还是有一定局限性的。Object.defineProperty只能劫持对象属性,所以我们需要遍历每个对象的每个属性。在Vue2.x中,数据监控是通过递归+遍历数据对象来实现的。如果属性值也是一个对象,那么就需要深度遍历。显然,劫持一个完整的对象是更好的选择。Proxy可以劫持整个对象并返回一个新的对象。Proxy不仅可以代理对象,还可以代理数组。也可以代理动态增加的属性。前端高级面试题详解created和mountedcreated的区别:在模板渲染成html之前调用,也就是一般会初始化一些属性值,然后渲染成view。mounted:模板渲染成html后调用,一般是初始化页面完成后调用,然后在html的dom节点上进行一些需要的操作。简而言之,就是先将Vue.js的模板编译转化为AST树,然后渲染函数返回VNode(Vue的虚拟DOM节点)。详细步骤如下:首先,通过compile编译器将模板编译成AST语法树(抽象语法树是源代码抽象语法结构的树表示),compile是createCompiler的返回值,createCompiler用于创建编译器。此外,compile还负责合并选项。然后,AST会通过generate(将AST语法树转化为render函数字符串的过程)得到render函数。render的返回值是VNode,也就是Vue的虚拟DOM节点,里面包含了(标签名、子节点、文本等)生命周期钩子是如何实现的?Vue的生命周期钩子的核心实现是使用发布-订阅模型,先订阅用户传入的生命周期钩子(内部存储在一个数组中),然后在创建组件实例的过程中执行相应的钩子方法(release)once相关代码如下if(handlers){for(leti=0;iast->渲染函数Vue在将执行模板编译版本compileToFunctions的代码,将模板转换为渲染函数://将模板编译为渲染函数const{render,staticRenderFns}=compileToFunctions(template,options//omitted},this)复制代码CompileToFunctions中的主要逻辑如下:(1)调用parse方法将模板转换成ast(抽象语法树)constast=parse(template.trim(),options)复制代码parse的目标:将tamplate转换成AST树,这是描述整个模板的一种方式以JavaScript对象的形式存在。解析过程:使用正则表达式顺序解析模板。在解析开始标签、结束标签和文本时,会分别执行相应的回调函数,从而达到构建AST树的目的。AST元素节点分为三种类型:1表示普通元素,2表示表达式,3表示纯文本(2)优化静态节点optimize(ast,options)copycode这个过程主要分析哪些是静态节点,给个标记,后续更新渲染可以直接跳过静态节点,优化AST的深度遍历,检查每棵子树的节点元素是静态节点还是静态节点根。如果它们是静态节点,它们生成的DOM永远不会改变,这是对运行时模板更新的一个很好的优化。(3)生成代码constcode=generate(ast,options)复制代码generate将ast抽象语法树编译成render字符串并将static部分放入staticRenderFns,最后通过newFunction(`render`)生成render函数.Vue数据中某个属性的值发生变化后,视图会立即同步重新渲染吗?重新渲染不会立即同步执行。Vue对响应式的实现并不是在数据发生变化后立即改变DOM,而是按照一定的策略更新DOM。Vue在更新DOM时异步执行。只要检测到数据变化,Vue就会打开一个队列,缓冲所有发生在同一个事件循环中的数据变化。如果同一个观察者被多次触发,它只会被推入队列一次。这种缓冲时的重复数据删除对于避免不必要的计算和DOM操作非常重要。然后,在下一个事件循环节拍中,Vue刷新队列并执行实际的(去重)工作。你对你的Vue项目做了哪些优化?(1)代码层面的优化v-if和v-show区分使用场景与computed和watch场景v-for遍历必须给item添加key,避免同时使用v-if长列表性能优化事件破坏图片资源lazy加载路由第三方插件的延迟加载按需引入无限列表性能优化服务端渲染SSR或预渲染(二)Webpack层面的优化Webpack对图片进行压缩,减少冗余代码,从ES6到ES5提取常用代码模板预编译提取ComponentCSS优化SourceMap构建结果输出分析Vue项目编译优化(三)Web基础技术优化启用gzip压缩浏览器缓存CDN使用ChromePerformance寻找性能瓶颈为什么不建议使用索引作为钥匙?使用index作为key和不写基本是一样的,因为不管数组的顺序怎么颠倒,index都是0,1,2...这样排列,Vue会重用错误的旧子节点并做很多额外的工作。Vue-router路由有哪几种模式?一般有两种模式:(1)**hash模式**:对于hash值的后续变化,浏览器既不会向服务器发送请求,也不会刷新浏览器,hash值的每一次变化都会触发一次哈希更改事件。(2)**历史模式**:利用HTML5中新的pushState()和replaceState()方法。这两个方法应用于浏览器的历史堆栈。在已有的back、forward、go的基础上,提供了修改历史的功能。只是当他们进行修改的时候,虽然改变了当前的URL,但是浏览器并不会立即向后端发送请求。说说Vue和React组件化的思路1、我们在开发每个页面的时候,都会有很多重复的功能,比如element中的xxxx。像这样的纯非页面UI成为了我们常用的UI组件,而原来的前端组件只指UI组件2。随着业务逻辑越来越多,我们希望我们的组件能够处理很多事情,这就是我们常说的组件化。该组件不是UI组件,而是包含特定服务的业务组件。3、这种开发思路就是分而治之。将开发难度和维护成本的影响降到最低。并且可以多人协作,每个人写不同的组件,最后像搭积木一样组成页面$nextTick原理及作用Vue的nextTick的本质是JavaScript执行原理EventLoop的应用。nextTick的核心是使用原生的JavaScript方法,如Promise、MutationObserver、setImmediate、setTimeout等来模拟实现相应的微/宏任务。本质就是利用JavaScript的这些异步回调任务队列,在Vue框架中实现自己的异步回调队列。.nextTick不仅是Vue内部异步队列的调用方法,还可以让开发者在实际项目中使用该方法来满足实际应用中DOM更新数据时序的后续逻辑处理。nextTick是JavaScript底层执行原理的典型应用,具体案例中的例子,引入异步更新队列机制的原因:如果是同步更新,多次赋值一个或多个属性会频繁触发UI/DOM渲染,可以减少一些无用的渲染。同时,由于VirtualDOM的引入,每一次状态改变后,都会向组件发送状态改变信号,组件通过VirtualDOM计算具体需要更新的DOM节点,然后更新DOM。每次状态更新后的渲染过程需要更多的计算,而这种无用的工作会浪费更多的性能,所以异步渲染变得更加关键Vue采用了数据驱动视图的思想,但在某些情况下,DOM仍然需要被操纵。有时候,你可能会遇到这样一种情况,DOM1的数据发生了变化,DOM2需要从DOM1获取数据,这时你会发现DOM2的视图没有更新,这时就需要使用nextTick了。由于Vue的DOM操作是异步的,所以在上面的例子中,需要在$nextTick中写DOM2获取数据的操作。this.$nextTick(()=>{//获取数据的操作...})复制代码所以,在以下情况下,会用到nextTick:数据变化后执行的操作,这个操作需要当DOM结构随着数据的变化而变化时,这个操作需要在nextTick()的回调函数中。在vue生命周期中,如果在created()钩子中进行DOM操作,也必须放在nextTick()的回调函数中。因为在created()钩子函数中,页面的DOM还没有渲染出来,此时是没有办法操作DOM的,所以这时候如果要操作DOM,就必须把操作代码在nextTick()的回调函数中。