vue响应式原理和vue2和vue3原理的区别
这道题问道的频率极高,就我经历的多场面试几乎都会问到,而且是面试到vue方面的开门题。
- vue2是根据
Object.defineproprety
Api来对数据进行劫持,并结合订阅-发布设计模式来实现的。vue3是用proxy
代理对象来实现的。 Object.defineproprety
只能代理属性,而proxy
能代理对象。- 对象新增属性
proxy
代理可以监听到,Object.defineproprety
监听不到。 Object.defineproprety
的代理行为是在破坏原对象的基础上实现的,proxy
代理则不会破坏原对象,只是在原对象上覆盖了一层。- 数组新增
proxy
代理可以监听到,Object.defineproprety
监听不到。 proxy
代理不兼容IE11及以下。
vue中的nextTick是干什么用的?
在vue中修改响应式数据后并不会马上出发dom更新,而是把需要更新的watcher
加入quequeWacher
队列中。如果我们需要在数据更新后马上获取到变化后的dom就需要在nextTick
函数中进行获取到变化后的dom。
nextTick原理
是借助浏览器的事件循环来完成的,因为每次事件循环之间都有一次视图渲染,nextTick
使用promise
来实现的,当浏览器不支持promise
时就会降级使用setImmediate
,setTimeout
来实现。
vue2和vue3的区别
- vue2是选项式API,vue3是组合式API。选项式API各个方法是分散的,组合式API是根据功能进行自由组合的,可以讲data,methods,compute等按照功能划分放在一起。
- vue2是讲响应式数据放在data里的,vue3是通过
ref
或者reactive
讲数据声明为响应式的。 - vue2响应式数据是通过
Object.defineproprety
劫持数据来实现的,vue3是通过Proxy
代理来实现的。 - vue3将生命周期中
beforeCreate
和created
合并到setup
函数中。 - vue3可以有多个根节点,vue2只能有一个。
- vue3新增了传送组件Teleport和异步依赖处理组件Suspense。
什么是虚拟dom
就是描述dom结构的js对象
为什么要用虚拟dom
- 原生dom渲染开销很大。
- 虚拟dom就是为了减少原生dom渲染的次数,通过diff算法找到差异部分来渲染到dom上。
说一下diff算法
diff算法本质上是找出两个对象之间的差异,目的是尽可能复用节点,在vue中状态发生改变时用来计算改变前的虚拟dom和改变后的虚拟dom之间的差异的算法。
简述vuex
面试问到这个问题的时候,不要上来就开始说什么state,mutation...。你要先阐述Vuex干嘛用的,什么时候需要用Vuex。
- vuex是全局状态管理器,可以管理应用内所有组件的状态,并不是每个项目都需要引入vuex,只有当这些页面共享着多个数据的状态时才应该引入vuex。
- vuex有三个核心概念,
state
,mutations
,actions
,其中,state
是存放数据的地方,mutations
中的函数则是用来修改state
数据的,也只能用来修改state
数据,并且不能执行异步操作。actions
是用来处理异步操作的,比如发送异步请求,然后调用mutation
中的函数来修改state
。 - vuex还有两个概念,
getters
,modules
,getters
类似计算属性中的computed
一样用来描述依赖响应式数据变化的复杂逻辑处理。modules
则是用分割仓库为模块的,便于项目的维护管理,每个module
都有自己的,state
,mutations
,actions
。
简述pinia
pinia其实就是vuex5,和vuex4的区别主要是
- pinia使用更简单,更符合开发者习惯。
- pinia中没有
mutations
,状态state
可以直接修改,或者在actions
中修改,或者使用它的$patch
方法修改。 - pinia中没有
modules
,如果想有多个store
,直接使用defineStore
定义多个store
传入不同的id
即可。 - 更好的TS支持。
vue-router是什么,描述一下它的原理?
vue-router是vue官方的路由管理器,有hash和history两种模式
hash
就是通过监听hashchange
事件来实现更新页面部分内容的操作,url后面会带有#
号。
history
通过监听popstate
事件来实现更新页面部分内容的操作,原理和hash
模式一样,只是url后不会有#
号,点哪个url就用url替换掉浏览器当前显示的url。
说一下路由守卫?
路由守卫通俗理解就是一种中间件用于路由跳转时处理一些特殊操作,例如,登录验证,权限验证等。
路由守卫分为三种,全局守卫
,路由独享守卫
,组件路由守卫
全局守卫
beforeEach
,接收三个参数,to
,from
,next
,每个路由跳转前都会触发,一般用于登录验证比较多。beforeResolve
, 和beforeEach
类似,区别是在导航确认前,同时在所有组件内守卫和异步路由组件被解析之后调用。afterEach
,在路由完成跳转后调用,接收,to
,from
两个参数。
路由独享守卫
beforeEnter
,一般配置在路由配置文件中(router/index.js)
,对进入某个路由之前进行相关操作。
组件路由守卫
统一接收
to
,from
,next
三个参数
beforeRouteEnter
,在进入路由之前调用,无法获取到vue实例。beforeRouteUpdate
,在当前路由改变,但是该组件被复用时调用。beforeRouteLeave
,在离开组件时调用。
跨域的解决方案
- 前端配置开发时的代理转发规则用于开发期间解决跨域问题
- 服务端配置nginx端口转发解决跨域,这是比较通用的方案,开发和部署都可。
- 可以将打包后的静态文件放到后端可访问文件目录,同源了就没有跨域问题了,但这只能用于部署。
- 服务端配置跨域策略,放行浏览器发送的
options
请求。