前端面试题之Vue系列
前端面试题之Vue系列
目录
- 1、双向数据绑定的原理
- 2、使用Object.definProperty()来进行数据劫持有什么缺点
- 3、MVVM、MVC、MVP的区别
- 4、Computed和Watch的区别
- 5、Computed和Methods的区别
- 6、slot是什么?有什么作用
- 7、如何保持页面当前的状态
- 8、常见的事件修饰符及其作用
- 9、v-if,v-show,v-html的原理,区别
- 10、Vue组件data为什么必须是个函数而Vue的根实例则没有此限制?
- 11、对keep-alive的理解
- 12、Vue中封装的数组方法有哪些,其如何实现页面更新
- 13、Vue单页应用与多页应用的区别
- 14、Vue template到render的过程
- 15、Vue data中的某一个属性的值发送改变后,视图会立即同步执行重新渲染吗
- 16、对React和Vue的理解,它们的异同
- 17、Vue的优点
- 18、Vue如何监听对象或者数组某个属性的变化
- 19、对SSR的理解
- 20、Vue性能优化有哪些
- 21、简单说下Vue的生命周期
- 22、create和mounted的区别
- 23、一般在那个生命周期请求异步数据
- 24、组件通信
- 25、v-if和v-for哪个优先级更高?如果两个同时出现,应该怎么优化得到更好的性能?
- 26、你知道vue中key的作用和工作原理吗?说说你对它的理解
- 27、你怎么理解Vue中的diff算法
- 28、Vue组件化的理解
- 29、谈一谈对Vue设计原则的理解?
- 30、你对Vue3.0的新特性有没有了解?
- 31、路由的hash和history模式的区别
- 32、如何获取页面的hash变化
- 33、$route和 $router的区别
- 34、params和query的区别
- 35、对前端路由的理解
- 36、Vuex的属性
- 37、Vuex中action和mutation的区别
- 38、Vuex和localStorage的区别
- 39、Redux和Vuex有什么区别,它们的共同思想
- 40、Vue3.0有什么更新
- 41、defineProperty和proxy的区别
- 42、Vue3.0为什么要用Proxy
- 43、对虚拟DOM的理解
- 44、虚拟DOM真的比真实DOM性能好蛮
- 45、diff算法的原理
- 46、Vue中的key的作用
1、双向数据绑定的原理
vue.js
采用的数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()
来劫持各个属性的setter
,getter
,在数据变动的时发布消息给订阅者watcher
,触发相应的监听回调,然后去更新视图。
2、使用Object.definProperty()来进行数据劫持有什么缺点
在对一些属性进行操作时,使用这种方法无法拦截,比如通过下标方式修改数组数据或者给对象新增属性,这都不能触发组件的重新渲染,因为Object.defineProperty
不能拦截到这些操纵。更精确的来说,对于数组而言,大部分操作都是拦截不到的,只是Vue内部通过重写函数的方式解决了这个问题。
在Vue3.0中已经不使用这种方式了,而是通过使用Proxy
对对象进行代理,从而实现数据劫持。Proxy
的好处是它可以完美的监听到任何方式的数据改变,唯一的缺点是兼容性的问题,因为Proxy
是ES6的语法。
3、MVVM、MVC、MVP的区别
这三者都是框架模式,它们设计的目标都是为了解决Model
和View
的耦合问题。
MVC 通过分离 Model
、View
和 Controller
的方式来组织代码结构。主要应用于后端,它的优点是分层清晰,缺点是数据混乱,灵活性带来的维护性问题。
MVP是MVC的进化形式。MVP 模式与 MVC 唯一不同的在于 Presenter
和 Controller
。Presenter
可以理解为一个中间人,它负责View
和Model
之间的数据流动,防止View
和Model
之间直接交流。因为在 MVC 模式中使用观察者模式,来实现当 Model
层数据发生变化的时候,通知 View
层的更新。这样 View
层和 Model
层耦合在一起,当项目逻辑变得复杂的时候,可能会造成代码的混乱,并且可能会对代码的复用性造成一些问题。
MVP的模式通过使用Presenter
来实现对View
层和Model
层的解耦。但如果应用逐渐变大,会导致presenter
的体积增大,难以维护。
MVVM模式在前端领域有广泛应用,Model
和View
并无直接关联,而是通过ViewModel
来进行联系的,Model
和ViewModel
之间有着双向数据绑定的联系,因此当Model
中的数据改变时会触发View
层的刷新。分离视图和模型,降低代码耦合,提高视图或者逻辑的重要性,提高可测试性,自动更新dom。
4、Computed和Watch的区别
- computed是计算属性;watch是监听,监听data中的数据变化;
- computed支持缓存,当其依赖的值发送变化的时候,计算属性会重新计算,反之,则使用缓存中的属性值;watch不支持缓存,当对应属性发送变化的时候,响应执行;
- computed不支持异步,有异步操作时无法监听数据变化;watch支持异步操作;
- computed第一次加载时就监听;watch默认第一次加载时不监听
- computed中的函数必须调用return;watch不是
- 使用场景:
- 一个属性受到多个属性影响,如购物车商品结算,可以使用computed
- 一个数据响应多条数据,如,搜索数据,可以使用watch
5、Computed和Methods的区别
可以将同一函数定义为一个method或者一个计算属性。对于最终的结果,两种方式是相同的。
不同点:
- computed计算属性是基于它们的依赖进行缓存的,只有在它的相关依赖发送改变时才会重新求值
- method调用总会执行该函数
6、slot是什么?有什么作用
在html中slot元素,是Web组件里面的一个占位符,该占位符可以在后期使用自己的标记语言填充。我们可以理解为slot在组件模板中占好了位置,当使用该组件标签时候,组件标签里面的内容就会自动填充。
使用场景:
- 通过插槽可以让用户可以拓展组件,去更好的复用组件和对其做定制化处理;
- 通过slot插槽向组件内部指定位置传递内容,完成这个复用组件在不同场景的应用,比如布局组件,表格列,下拉选,弹框显示内容等。
7、如何保持页面当前的状态
页面状态出现的两种情况:
- 前组件会被卸载
- 前组件不会被卸载
【组件会被卸载】:
-
将状态存储在LocalStorage/SessionStorage
-
优点:
- 兼容性好,不需要额外库或工具
- 简单快捷,基本可以满足大部分需求
-
缺点:
- 状态通过 JSON 方法储存(相当于深拷贝),如果状态中有特殊情况(比如 Date 对象、Regexp 对象等)的时候会得到字符串而不是原来的值。
- 如果 B 组件后退或者下一页跳转并不是前组件,那么 flag 判断会失效,导致从其他页面进入 A 组件页面时 A 组件会重新读取 Storage,会造成很奇怪的现象
-
-
路由传值,query,params,prop
-
优点:
- 简单快捷,不会污染LocalStorage/SessionStorage
- 可以传递Date、RegExp等特殊对象
-
缺点:
- 如果A组件可以跳转至多个组件,那么在每个跳转组件内部都要写相同的逻辑
-
【组件不会被卸载】:
-
单页面渲染:要切换的组件要全屏渲染,前组件中正常储存页面状态。
-
优点:
- 代码量少
- 不需要考虑状态传递过程中的错误
-
缺点:
- 增加A组件维护成本
- 需要传入额外的prop到其他组件
- 无法利用路由定位页面
-
-
在Vue中,可以使用keep-alive来缓存页面,隐藏组件时不会被销毁,被缓存到内存中,下次使用会被激活
<keep-alive>
<component :is="cName"> </component>
</keep-alive>
keep-alive对应的生命周期函数
- 当组件被缓存时,会自动触发组件的deactivated生命周期
- 当组件被激活时,会自动触发组件的activated生命周期函数
8、常见的事件修饰符及其作用
.stop
防止事件冒泡
.prevent
防止执行预设的行为
.capture
捕获
.self
只会触发自己范围内的事件,不包含子元素
.once
只会触发一次
9、v-if,v-show,v-html的原理,区别
- v-if 会调用
addIfCondition
方法,生成vnode
的时候会忽略对应节点,render
的时候就不会渲染; - v-show 会生成
vnode
,render
的时候也会渲染成真实节点,只是在render
过程中会在节点的属性中修改show
属性值,也就是常说的display
; - v-html 通过
addProp
设置innerHTML
为v-html的值
区别:
- 手段:v-if是动态向DOM树内添加或者删除DOM元素;v-show是通过设置DOM元素的display样式属性控制显隐;
- 编译过程:v-if切换有一个局部编译/卸载的过程,切换过程中合适的销毁和重构内部的事件监听和子组件;v-show只是简单的基于css切换;
- 编译条件:v-if是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译;v-show是在任何条件下,无论首次条件是否为真,都被编译,然后被缓存,而且DOM元素保留;
- 性能消耗:v-if有更高的切换消耗;v-show有更高的初始渲染消耗;
- 使用场景:v-if适合运行条件不大可能改变;v-show使用频繁切换
10、Vue组件data为什么必须是个函数而Vue的根实例则没有此限制?
源码:src/core/instance/state.ts中的initData()
Vue组件可能存在多个实例,如果使用对象形式定义data,则会导致它们共用一个data对象,那么状态变更将会影响所有的组件实例,这是不合理的;采用函数形式定义,在initData
时会将其作为工厂函数返回一个全新data对象,有效避免多个实例之间状态污染问题。而在Vue根实例创建过程中则不存在该限制,也是因为根实例只能有一个,不需要担心这种情况。
你把data设置为对象也会报错
11、对keep-alive的理解
(1)Keep-alive是什么
vue自带的一个组件,用来缓存组件的,提升性能
keep-alive有以下二个属性:
- include 属性用来指定只有名称匹配的组件会被缓存,多个组件名之间使用英文的逗号分隔;
- exclude 属性是用来排除项,注意与include不能同时使用
keep-alive对应的生命周期函数:
- 当组件被缓存时,会自动触发组件的deactivated生命周期
- 当组件被激活时,会自动触发组件的activated生命周期函数
(2)使用场景
使用原则:当我们在某些场景下不需要让页面重新加载时我们可以使用keep-alive
12、Vue中封装的数组方法有哪些,其如何实现页面更新
Vue将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新,这些被包裹过的方法包括:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
简单的说,重写了数组中的那些原生方法,首先获取到这个数组的Observer
对象,如果有新的值,就直接调用observeArray
继续对新的值观察变化,然后手动调用notify/ˈnōdəˌfī/
,通知watcher
,执行update
。
13、Vue单页应用与多页应用的区别
-
SPA单页面应用,指只有一个主页面的应用,一开始只需要加载一次js,css等相关资源。所有内容都包含在主页面,对于每个功能模块组件化,单页应用跳转,就是切换相关组件,仅仅刷新局部资源。
-
优点:
- 用户体验好,快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染
- SPA相对服务器压力小
- 前后端职责分离,架构清晰,前后端进行交互逻辑,后端负责数据处理
-
缺点:
- 初次加载耗时多
- SEO难度大,由于所有的内容都在一个页面中动态替换显示,所有SEO上其有着天然的弱势。
-
-
MPA多页面应用,指有多个独立页面的应用,每个页面都必须重复加载js、css等相关资源。多页应用跳转,需要整页资源刷新
14、Vue template到render的过程
15、Vue data中的某一个属性的值发送改变后,视图会立即同步执行重新渲染吗
不会立刻同步执行重新渲染。在vue实例初始化后,会将data设置为响应式对象,比如:当我们执行this.xxx = 1时,会触发这个响应式对象的setter。在setter中,会触发更新,通知所有的订阅了xxx的订阅者。但是这个触发更新并不是同步的,它会将所有的watcher都添加到一个队列,并在nextTick之后去更新视图。——(这样做的目的是减少对DOM的操作)
$nextTick
是在下一次DOM更新循环结束之后执行延迟回调,在修改数据之后使用$nextTick
16、对React和Vue的理解,它们的异同
【相同之处】:
- 都将注意力集中保持在核心库,而将其他功能如路由和全局状态管理交给相关的库;
- 都有自己的构建工具,能让你得到一个根据最佳实践设置的项目模板
- 都使用了虚拟DOM提高重绘性能;
- 都有props的概念,允许组件间的数据传递;
- 都鼓励组件化应用,将应用分拆成一个个功能明确的模块,提高复用性
【不同之处】:
-
数据流
- vue默认支持数据双向绑定,而React一直提倡单向数据流
-
虚拟DOM
- Vue2.x开始引入虚拟DOM,可以更快的计算出 Virtual DOM(虚拟DOM)的差异,这是由于它在渲染过程中,会跟踪每一个组件的依赖,不需要重新渲染这个组件树;
- React,每当应用的状态被改变时,全部子组件都会重新渲染。
-
组件化
- Vue鼓励写近似常规HTML的模板。
- React推荐你所有的模板通用JavaScript的语法扩展——JSX书写(相当于把html代码写在JavaScript中)
-
高阶组件
- React可以通过高阶组件HOC来扩展,而Vue需要通过mixins来扩展
- 高阶组件就是高阶函数,而React的组件本身就是纯粹的函数,所以高阶函数对React来说易如反掌。相反Vue.js使用HTML模板创建视图组件,这是模板无法有效的编译,因此Vue不能采用HOC来实现。
-
构建工具
- React——>Create React App
- Vue——>vue-cli
17、Vue的优点
易用,灵活和高效。
Vue提供数据响应式,声明式模板语法和基于配置的组件系统等核心特性,这些是我们只需要关注应用的核心业务,大大减少了我们的难度。再就是比较灵活,因为vue是渐进式框架,可以作为第三方库插入到应用程序中去,再就是超快的虚拟DOM和diff算法使我们的应用拥有最佳的性能表现。
18、Vue如何监听对象或者数组某个属性的变化
当在页面中直接设置数组的某一项的值,或者直接设置对象的某一个属性值,这个时候,你会发现页面并没有更新。这是因为Object.defineProperty()
限制,监听不到变化。
解决方法:
- vm.$set / Vue.set (你要改变的数组/对象,你要改变的位置key,你要改成什么value)
- 调用以下数组方法:splice()、pop()、push()、shift()、unshift()、sort()、reverse()
19、对SSR的理解
SSR服务端渲染就是在服务端进行渲染生成html文件,浏览器世界显示生成html文件。
SSR优点:
1、可以很好的解决首页需要加载js和css导致页面加载缓存慢的问题,SSR直接将HTML字符串传递给浏览器,加快了首屏加载时间;
2、优化SEO,SSR生成的HTML是有内容的,这让搜索引擎能够索引到页面的内容;
3、服务端渲染不用关心浏览器兼容性问题,运算过程都在服务端完成,避免了浏览器兼容同时也能为客户省电
SSR缺点:
1、由于运算都在服务器完成,所以就需要服务器能够承担的负载更高;
2、增加开发的复杂程度,构建和部署;
20、Vue性能优化有哪些
1.路由懒加载
2、keep-alive缓存页面
3、使用v-show复用DOM
4、v-for遍历避免同时使用v-if
5、长列表性能优化
(1)如果列表是纯粹的数据展示,不会有任何变化,就不需要做响应式
this.users = Object.freeze(users); // 把这些列表锁死,不需要做响应式
(2)如果是大数据长列表,可采用虚拟滚动,只渲染少部分区域的内容
6、事件的销毁
Vue组件销毁时,会自动解绑它的全部指令及事件监听器,但是仅限于组件本身的事件。
7、图片懒加载
<img v-lazy="/static/img/1.png">
参考 vue-lazyload
8、第三方插件按需引入
9、SSR服务端渲染
21、简单说下Vue的生命周期
每个vue实例在被创建时都要经过一系列的初始化过程,例如,需要设置数据监听,编译模板,将实例挂载到DOM并在数据变化时更新DOM等,同时在这个过程中也会运行一些叫做生命周期钩子的函数:
22、create和mounted的区别
- created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
- mounted:已经把内存中的HTML结构,成功的渲染到了浏览器之中。此时浏览器中已经包含了当前组件的DOM结构
23、一般在那个生命周期请求异步数据
我们可以在钩子函数 created、beforeMount、mounted中进行调用,因为在这三个钩子函数中,data已经创建,可以将服务端返回的数据进行赋值。
推荐在created钩子函数中调用异步请求,因为在created钩子函数中调用异步请求有以下优点:
- 能更快获取到服务端数据,减少页面加载时间,用户体验更好
- SSR服务端不支持beforeMount、mounted钩子函数,放在created中有助于一致性
24、组件通信
1、props/$emit
父组件通过props向子组件传递数据,子组件通过$emit和父组件通信
2、eventBus事件总线($emit发送 / $on接受)
3、依赖注入(Provide/inject)可以用在父子之间的通信,也可以用在祖孙之间的通信
4、ref/$refs
5、$parent
/$children
(无序数组)
6、$attrs
/$listeners
25、v-if和v-for哪个优先级更高?如果两个同时出现,应该怎么优化得到更好的性能?
v-for的优先级大于v-if,答案在源码compiler/codegen/index.js
<p v-for="child in children" v-if="isFolder">{{child.title}}</p>
// 如果v-for和v-if同时出现,每次渲染都会先执行循环再判断条件,无论如何循环都不可避免,浪费了性能
// 要避免出现这种情况,则在外层嵌套template,在这一层进行v-if判断,然后再内部进行v-for循环
<template v-if="isFolder">
<p v-for="child in children">{{child.title}}</p>
</template>
26、你知道vue中key的作用和工作原理吗?说说你对它的理解
源码:src/core/vdom/patch.ts 中的 updateChildren()
key的作用主要是为了高效的更新虚拟DOM,其原理是vue在patch过程中会执行updateChildren方法,它会去更新所有的两个新旧的子元素,通过key精准的去判断当前循环中两个节点是否是同一个,如果没有加key永远认为是相同节点(因为是先会比较两个节点的key),会强制更新,这样在这过程中,我们就无法避免频繁的更新元素,性能就比较差。如果加上key,通过首尾比较,元素位置不会频繁的移动,提高性能。
27、你怎么理解Vue中的diff算法
diff算法是虚拟DOM技术的必然产物,如果有用到虚拟DOM,必然就会用到diff算法。通过将新旧虚拟DOM对比(即diff),将变化的地方更新在真实的DOM上;两棵树在比较的过程中,时间的复杂度为O(n^3),引入diff算法,它的复杂度为O(n)因为只会比较同一层,不会跨层比较。
Vue2.x中为了降低watcher粒度,每个组件只有一个watcher与之对应,只有引入diff才能精确的找到发生变化的地方。数据发生变化后,由于数据响应式会触发setter,之后通知watcher,把watcher添加到异步更新队列中去,在每一次事件循环结束的时候,会清空事件队列,所有的watcher都会尝试的执行它们的更新函数,这些更新函数其实执行组件的渲染函数和组件更新函数,比较新旧虚拟DOM,这个时刻是Diff的触发时刻,对比更新DOM的过程称为patch。
diff过程整体遵循深度优先、同层比较的策略;两个节点之间比较会根据它们是否拥有子节点或者文本节点做不同操作;首先假设头尾节点可能相同,做4次对比尝试,如果没有找到相同节点才按照通用方式遍历查找,查找结束再按情况处理剩下的节点。通常借助key可以非常精确找到相同节点,因此整个patch过程非常高效。
28、Vue组件化的理解
回答总体思路:
组件化定义,优点,使用场景和注意事项等方面展开陈述,同时强调vue中组件化的一些特点
组件是独立和可复用得到代码组织单元。组件系统是Vue核心特性之一,它使开发者使用小型,独立和通常可复用的组件构建大型应用;
Vue中常见的组件技术有:属性prop,自定义事件,插槽等,它们主要用于组件通信、扩展等;
优点:
合理的划分组件,有助于提升应用性能;
组件开发能大幅提高应用开发效率、测试性、复用性等;
组件应该是高内聚,低耦合的,遵循单向数据流的原则。
29、谈一谈对Vue设计原则的理解?
1、渐进式JavaScript框架
与其他大型框架不同的是,Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层,不仅容易上手,还便于与第三方库或既有项目整合,简单的说可以将Vue.js作为应用的一部分嵌入其中,带来更加丰富的交互体验。
2、易用,灵活和高效
Vue提供数据响应式,声明式模板语法和基于配置的组件系统等核心特性,这些是我们只需要关注应用的核心业务,大大减少了我们的难度。再就是比较灵活,因为vue是渐进式框架,可以作为第三方库插入到应用程序中去,再就是超快的虚拟DOM和diff算法使我们的应用拥有最佳的性能表现。
30、你对Vue3.0的新特性有没有了解?
1、更快
虚拟DOM重写;
优化slots的生成;
- Vue3中可以单独渲染父级和子级,确保实例正常的跟踪依赖关系,避免不必要的父子组件重新渲染。
静态树提升;
- 检查静态节点,然后将其提升,从而降低了渲染成本
静态属性提升;
- Vue3打补丁时跳过这些属性不会改变的节点
基于Proxy的响应式系统;
- 组件实例初始化的速度提高100%,节省内存开销,加快速度,但是存在低浏览器版本的不兼容
2、更容易维护:TypeScript + 模块化
3、更友好
跨平台:编译器核心和运行时核心与平台无关,使得eVue更容易与任何平台(Web,Android,iOS)一起使用
4、更容易使用
改进的TypeScript支持,编译能提供强有力的类型检查和错误及警告;
更好的调式支持;
独立的响应化模块;
Composition API;
31、路由的hash和history模式的区别
Vue-Router有两种模式:hash模式和history模式。默认路由模式是hash模式
1、hash模式
简介:hash模式是开发中默认的模式,它的URL带着一个#,例如:http://www.abc.com/#/vue 它的hash值就是#vue
特点:
1、hash变化会触发网页跳转,即浏览器的前进、后退
2、hash变化不会刷新页面,SPA必需的特点
3、hash永远不会提交到server端
2、history模式
history模式的URL中没有#,它使用的是传统的路由分发模式,即用户在输入一个URL时,服务器会接受这个请求,并解析这个URL,然后做出相应的逻辑处理。
特点:
1、比hash模式要好看些
2、history需要后台配置支持,如果没有后台的正确配置,访问时就会返回404
32、如何获取页面的hash变化
1、监听$route,一般获取路由信息,包括路径,query,params,hash等
2、window.location.hash读取#值
33、$route和 $router的区别
- $route 一般获取路由信息,包括路径、query、params、hash等
- $router 一般进行编程式导航和路由跳转,包括push、replace
34、params和query的区别
-
params传参只能由name引入路由,如果写成path页面会显示undefined报错,不会在url中显示;
-
query可以使用name或path;
-
URL显示:query在浏览器地址栏中显示参数,params不显示;
-
刷新:query刷新不会丢失query里面的数据,params刷新会丢失params里面的数据
相同的地方:两者获取传参内容大概一致
{{this.$route.query.keyword}}
{{this.$route.params.keyword}}
35、对前端路由的理解
在前端技术早期,一个url对应一个页面,如果要从A页面切换到B页面,那么必然伴随着页面的刷新。这个体验并不是很好,不过在最初也是无奈之举——用户只有在刷新页面的情况下,才可以重新去请求数据。
后来,ajax出现了,它允许人们在不刷新页面的情况下发起请求,在这样的背景下,出现了SPA单页面应用。
SPA极大地提升了用户体验,它允许页面不刷新的情况下更新页面内容,使内容的切换更加流畅,但是没有考虑到“定位”这个问题——内容切换后,页面的URL还是一样的,这就带来了两个问题:
- 不知道当前页面进展到了哪一步
- 由于有且只有一个URL给页面做映射,这对SEO也不够友好,搜索引擎无法收集全面的信息
为了解决这个问题,前端路由出现了。
前端路由可以在我们仅只有一个页面的情况下,“记住”用户当前走到了哪一步——意味着用户前进,后退触发新的内容都会映射到不同的URL上去。此时即便它刷新页面,当前的URL可以标识出它所在的位置,因此内容也不会丢失。
前端路由解决思路:
- 拦截用户的刷新操作,避免服务端盲目的响应,返回不符合预期的资源内容。把这个刷新动作完全放到前端逻辑里消化掉
- 感知URL的变化,一旦感知到,就根据这些变化,用JS去生成不同的内容
36、Vuex的属性
Vuex是一个专门Vue.js应用程序开发的状态管理模式库,它采用集中式存储管理应用的所有组件的状态。
核心模块:
store 仓库
getter可以认为是store的计算属性
mutation更改vuex的store中的状态事件
action 异步事件
- Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
module 模块
由于使用单一状态树,应用的所有状态都会集中到一个比较大的对象。当应用变得非常复杂时,store对象就可能变得相当臃肿。为了解决以上问题,vuex允许我们将store分割成模块。每个模块都有自己的state、mutation、action、getter
37、Vuex中action和mutation的区别
- mutation中的操作是一系列的同步操作,用于修改state中的变量的状态。
- action可以包含任意异步操作,提交的是mutation,而不是直接变更状态。
38、Vuex和localStorage的区别
(1)最重要的区别
- vuex存储在内存中
- localStorage 则以文件的方式存储在本地,只能存储字符串类型的数据,存储对象需要JSON的stringify和parse方法进行处理。
(2)应用场景
- vuex是一个专门为Vue应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态。vuex用于组件之间的传值。
- localStorage是本地存储,是将数据存储到浏览器的方法,一般是在跨页面传递数据时使用
(3)永久性
刷新页面时vuex存储的值就会丢失,localStorage不会
39、Redux和Vuex有什么区别,它们的共同思想
vuex和redux都是状态管理库,用于单独管理状态,他们都应用了flux架构的思想。
其中redux是一个范用的库,可以单独使用,而Vuex是专门配置vue使用的;
redux的核心概念:action,reducer,store;
vuex的核心概念:action,getter,mutation,state
共同的思想:
单一的数据源、变化可以预测
40、Vue3.0有什么更新
1、更快
虚拟DOM重写;
优化slots的生成;
- Vue3中可以单独渲染父级和子级,确保实例正常的跟踪依赖关系,避免不必要的父子组件重新渲染。
静态树提升;
- 检查静态节点,然后将其提升,从而降低了渲染成本
静态属性提升;
- Vue3打补丁时跳过这些属性不会改变的节点
基于Proxy的响应式系统;
- 组件实例初始化的速度提高100%,节省内存开销,加快速度,但是存在低浏览器版本的不兼容
2、更容易维护:TypeScript + 模块化
3、更友好
跨平台:编译器核心和运行时核心与平台无关,使得eVue更容易与任何平台(Web,Android,iOS)一起使用
4、更容易使用
改进的TypeScript支持,编译能提供强有力的类型检查和错误及警告;
更好的调式支持;
独立的响应化模块;
Composition API;
41、defineProperty和proxy的区别
Vue 在实例初始化时遍历 data 中的所有属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。这样当追踪数据发生变化时,setter 会被自动调用。
缺点:
- 添加或删除对象的属性时,Vue 检测不到。因为添加或删除的对象没有在初始化进行响应式处理,只能通过$set 来调用Object.defineProperty()处理。
- 无法监控到数组下标和长度的变化。
Vue3使用Proxy来监控数据的变化。Proxy是ES6中提供的功能,其作用为:用于定义基本操作的自定义行为。
优点:
- Proxy直接代理整个对象而非对象属性,这样只需做一层代理就可以监听同级结构下的所有属性变化,包括新增属性和删除属性。
- Proxy可以监听数组的变化
42、Vue3.0为什么要用Proxy
Proxy的特点:
- 不需要使用Vue.set或vm.$set 触发响应式
- 全方位的数组变化检测,消除了Vue2无效的边界
- 支持Map、Set、WeakMap和WeakSet
43、对虚拟DOM的理解
虚拟DOM是对DOM的抽象,这个对象是更加轻量级的对DOM的描述。虚拟DOM本身是js对象。在代码渲染到页面之前,vue会把代码转为一个对象(虚拟DOM)。以对象的形式来描述真实DOM结构,最终渲染到页面。在每次数据发生变化之前,虚拟DOM都会缓存一份,变化之时,现在的虚拟DOM与缓存的虚拟DOM进行比较。在vue内部封装了diff算法,通过这个算法来进行比较,渲染时修改改变的变化。
44、虚拟DOM真的比真实DOM性能好蛮
没有虚拟DOM,当页面发送改变的时候会全部更新,即使没有变的也会删除掉重建。
虚拟DOM其实在js和真实dom中间加了一个缓存,利用diff算法避免了没必要的dom操作,从而提高了性能
45、diff算法的原理
diff算法是虚拟DOM技术的必然产物,如果有用到虚拟DOM,必然就会用到diff算法。通过将新旧虚拟DOM对比(即diff),将变化的地方更新在真实的DOM上;两棵树在比较的过程中,时间的复杂度为O(n^3)
,引入diff算法,它的复杂度为O(n)
因为只会比较同一层,不会跨层比较。
Vue2.x中为了降低watcher
粒度,每个组件只有一个watcher
与之对应,只有引入diff才能精确的找到发生变化的地方。数据发生变化后,由于数据响应式会触发setter,之后通知watcher,把watcher添加到异步更新队列中去,在每一次事件循环结束的时候,会清空事件队列,所有的watcher都会尝试的执行它们的更新函数,这些更新函数其实执行组件的渲染函数和组件更新函数,比较新旧虚拟DOM,这个时刻是Diff的触发时刻,对比更新DOM的过程称为patch。
diff过程整体遵循深度优先、同层比较的策略;两个节点之间比较会根据它们是否拥有子节点或者文本节点做不同操作;首先假设头尾节点可能相同,做4次对比尝试,如果没有找到相同节点才按照通用方式遍历查找,查找结束再按情况处理剩下的节点。通常借助key可以非常精确找到相同节点,因此整个patch过程非常高效。
46、Vue中的key的作用
key的作用主要是为了高效的更新虚拟DOM,其原理是vue在patch过程中会执行updateChildren方法,它会去更新所有的两个新旧的子元素,通过key精准的去判断当前循环中两个节点是否是同一个,如果没有加key永远认为是相同节点(因为是先会比较两个节点的key),会强制更新,这样在这过程中,我们就无法避免频繁的更新元素,性能就比较差。如果加上key,通过首尾比较,元素位置不会频繁的移动,提高性能。
更多推荐
所有评论(0)