具体内容结构(可作为回答思路)为:简略回答,详细回答
1、vue响应式
- 简略回答
Vue 2 响应式原理
- 数据劫持(Object.defineProperty)
- Vue 2 使用Object.defineProperty()来实现数据劫持。
- 它会遍历数据对象的所有属性,将每个属性转换为getter和setter。
- getter用于获取属性值,setter用于设置属性值并且在值被修改时通知相关的依赖进行更新。
Vue 内部会通过Dep(依赖收集器)和Watcher(观察者)来实现复杂的通知和更新流程。
- 依赖收集和更新机制
- 当组件渲染模板时,会访问数据对象的属性,触发getter,这时getter会收集依赖(也就是Watcher)。
- Watcher是一个函数,它会在数据变化时执行相应的更新操作,例如更新 DOM。
- 当数据发生变化,setter被触发,setter会通知所有收集到的Watcher,Watcher再执行相应的更新操作。
- 例如,在模板中有{{ message }}这样的插值表达式,当message的值发生变化时,对应的Watcher会重新渲染模板部分,更新 DOM 中显示message的地方。
- 局限性
- 对于对象新增属性和删除属性,不能自动进行响应式处理。
- 例如,在一个已经创建的 Vue 实例中,如果直接给vm.data添加一个新属性newProp,这个新属性不会自动成为响应式的。
- 需要使用Vue.set(或this.set在组件实例中)来将其转换为响应式。
Vue 3 响应式原理
- 基于 Proxy 代理对象
- Vue 3 采用Proxy来实现响应式。
- Proxy是一个原生的 JavaScript 对象,它可以代理另一个对象,拦截并处理该对象的基本操作,如属性的读取、设置、删除等。
- 例如,对于一个响应式数据对象:
reactive函数返回的state对象实际上是一个Proxy对象。当访问state.message时,Proxy会拦截这个操作并返回相应的值。当设置state.message为新的值时,Proxy也会拦截这个操作,并可以执行一些额外的操作,比如通知依赖更新。具体来说,Proxy的拦截操作可以通过一个handler对象来定义
- 深度响应式和自动更新
- Proxy可以很方便地实现深度响应式。
- 例如,对于一个嵌套的对象{ a: { b: 1 } },在 Vue 3 中,Proxy会自动代理内部的对象,使得对象内部的属性变化也能被正确地监测到。
- 当响应式数据发生变化时,和 Vue 2 类似,会通知相关的Watcher进行更新。
- 不过,Vue 3 在更新性能和效率上有了一些优化,例如通过静态提升和事件监听器缓存等技术,减少不必要的更新操作。
- 优势
- 能够自动处理对象属性的新增和删除。
- 在state对象中,如果添加一个新属性state.newProp = ‘New’,这个新属性会自动成为响应式的,不需要额外的操作,这使得数据操作更加自然和灵活。
- 同时,Proxy在处理复杂的数据结构,如嵌套对象和数组时,也能提供更好的性能和响应式体验。
- 详细回答
2、vuex和pinia区别
- 简略回答
- pinia源码采用TS编写,对TS 的支持更好。
- pinia去除了mutation,state的数据可以直接修改(解决表单不能使用v-model语法糖/计算属性代替)或提交同步的action,action支持同步和异步。
- 热更新更加便利(vite默认支持)
任何实现 import.meta.hot 规范工具都可以使用。
webpack 使用的是 import.meta.webpackHot。
- vuex是单store多模块,
- pinia是一个实例多store的方式,更加方便和灵活组合在compositionAPI形式里面使用。
- pinia支持服务器渲染
- 详细回答
3、谈谈你对vue的理解
- 简略回答
Vue是一个渐进式JavaScript框架,它专注于构建用户界面。
- Vue的核心思想是数据驱动和组件化。
- 通过将页面拆分成独立的组件,可以更好地管理代码,提高代码的复用性和可维护性。
- 详细回答
优势
- Vue的模板语法易于理解和学习,可以快速构建交互式的Web应用程序。
- Vue的生命周期钩子和自定义指令等功能,使得Vue可以满足各种复杂的需求。
- Vue还提供了Vuex、Vue Router等官方插件,可以进一步扩展Vue的功能。
使得Vue简单易用、灵活性高、性能卓越和扩展性强。
Vue的响应式数据绑定机制
- 通过对数据进行劫持和监听,可以实现数据的双向绑定,即数据变化会自动更新视图,同时视图的变化也会反映到数据上
- 这种机制使得Vue的数据流非常清晰和可预测,同时也减少了开发的工作量。
4、vue2和vue3有哪些区别
- 简略回答
- 响应式系统
- vue2使用Object.defineProperty()实现响应式数据。
- Vue3采用Proxy对象来实现响应式系统。
- 组件 API
- vue2 主要使用选项式API
- vue3 引入了组合式API,允许开发者使用函数来组织组件逻辑。组合 API 使得代码逻辑的复用更加方便。可以将相关的逻辑(如变量、方法、计算属性等)封装在一个函数或者一个自定义的组合函数中,然后在多个组件中复用。
- 性能优化
- 编译阶段
- 通过静态提升(Static Hoisting),可以将模板中的静态节点(不会发生变化的节点)提取出来,减少不必要的渲染更新。
- 事件处理函数不会再自动绑定this,这样可以避免一些不必要的性能开销和潜在的错误。
- 响应式系统的更新性能也有所提升,因为Proxy在处理复杂数据结构(如嵌套对象和数组)时能提供更好的性能和响应式体验。相比之下,Vue 2 在处理深层嵌套的响应式数据变化时,可能会因为深度遍历等操作而产生更多的性能开销。
- 生命周期钩子的变化
-
vue3 生命周期钩子有一些变化,beforeCreate和created被合并为setup函数(在setup函数中可以完成之前在这两个钩子中的操作)。beforeDestroy和destroyed被替换为beforeUnmount和unmounted。
-
新增了一些钩子,如onRenderTracked和onRenderTriggered,用于调试渲染性能相关的问题,它们可以帮助开发者更好地了解组件的渲染过程和触发更新的原因。
-
详细回答
5、vue next tick实现原理
- 简略回答
Vue.nextTick() 的实现原理是利用浏览器的异步任务队列,在 DOM 更新完成后执行回调函数。
- 详细回答
- 在某些情况下,我们需要在 DOM 更新完成后执行一些操作,这时就需要使用 Vue.nextTick() 方法。确保操作使用的是更新后的DOM
- Vue.js 会根据浏览器的支持情况选择合适的异步任务方法。
- 优先级最高的实现方式是 Promise,其次是MutationObserver和setImmediate,最后才是setTimeout
6、vue 在渲染列表的时候,为什么不建议用数组的下标当做列表的key值
- 简略回答
为了保证Vue渲染列表的性能和正确性,应该尽量避免使用数组下标作为key值。
- 详细回答
-
Vue渲染列表时,每个元素需要一个唯一的key值来标识自己,这个key值会被用来判断列表中哪些元素需要更新、删除或新增。
-
由于Vue的更新机制是基于diff算法实现的,使用数组下标作为key值会导致Vue无法正确地判断列表中元素的变化情况。
-
例如,当删除列表中某个元素时,其后面的所有元素的下标都会发生改变,导致Vue重新渲染整个列表。
-
为了避免这个问题,我们需要为每个元素提供一个稳定的、与其内容相关的唯一key值,
- 例如使用元素的id属性作为key值。这样,当列表中某个元素的内容发生变化时,其对应的key值也会发生改变,从而告诉Vue需要更新该元素。
7、谈一下对vuex的理解
- 简略回答
Vuex是Vue.js的状态管理库,用于管理Vue应用中的所有组件的共享状态
- 详细回答
-
Vuex的核心思想是将组件的共享状态抽离出来,以单独的状态树的形式存储,然后通过定义一系列的mutations、actions、getters来操作这个状态树。
-
Vuex的核心概念包括:state、mutations、actions和getters。
- state是应用的状态,
- 而mutations用于修改state中的状态。
- actions则用于处理异步操作或批量的同步操作,最终通过mutations来改变state。
- getters则用于对state中的数据进行计算或过滤。
-
Vuex中,数据流的流向是单向的,即从state到组件,再从组件到mutations/actions。
- 这种单向数据流的机制 使得数据的流动更加清晰,同时也更容易进行调试和维护。
- 而Vuex还提供了一些辅助函数,比如mapState、mapGetters、mapActions和mapMutations等,用于方便地访问和操作状态树。
8、vue-router
- 简略回答
Vue Router是Vue.js官方提供的一款路由管理器
- 通过监听URL变化,匹配路由规则,展示对应的组件内容,从而实现单页应用的路由控制。
- 通过路由匹配、路由模式、路由导航、路由组件等多个方面实现了完整的路由控制逻辑
- 详细回答
路由导航生命周期函数
- beforeEach:
在每次路由跳转之前执行,可以用来进行用户身份验证、路由拦截等操作。
- beforeResolve:
在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后执行。
- afterEach:
在每次路由跳转之后执行,可以用来进行路由跳转后的操作,比如页面滚动、统计PV等操作。
- beforeEnter:
在进入路由之前执行,与全局beforeEach的区别是它可以针对某个具体路由进行设置。
- beforeRouteUpdate:
在路由更新时执行,比如路由参数发生变化时。
- beforeRouteLeave:
在离开当前路由时执行,可以用来进行页面数据的保存或弹出提示等操作。
9、说下虚拟DOM和diff算法
- 简略回答
- 虚拟DOM是指用JavaScript对象模拟DOM树结构,包括节点的类型、属性和子节点等信息。
- diff算法是指在两个树形结构之间找出差异的算法。
- 详细回答
10、vue项目中style样式中为什么要添加 scoped
- 简略回答
Vue中使用 scoped 属性可以让样式作用域仅限于当前组件中
- 不影响全局
- 避免了样式污染和样式冲突的问题。
- 详细回答
11、mounted生命周期和keep-alive中activated的优先级
- 简略回答
优先级上 mounted 生命周期高于 activated 生命周期。
- 详细回答
- Vue 中,mounted 生命周期是指一个组件被挂载到 DOM 中后 触发的钩子函数。
- 而 keep-alive是一个用来缓存组件的抽象组件,它自身没有任何展示效果,只是将内部包含的组件缓存起来,从而能够在需要时快速地切换到缓存的组件。
- 当一个组件第一次被挂载时,mounted 生命周期会被触发, 同时 keep-alive 中的缓存组件还没有被渲染,因此 activated 生命周期并不会被触发。
- 只有当一个被缓存的组件被激活后(比如从其他页面返回到该组件所在的页面),activated 生命周期才会被触发。因此,优先级上 mounted 生命周期高于 activated 生命周期。
12、Vue 3.0 使用的 diff 算法相比 Vue 2.0 中的双端比对有以下优势
- 简略回答
相比 Vue 2.0 的双端比对,Vue 3.0 的 Diff 算法在复杂场景下更加高效。它减少了不必要的比较次数和节点移动操作。
- 详细回答
-
Vue 2.0 中的双端比对,对比的顺序是头头、尾尾、尾头
- 首先比较旧节点列表的头部和新节点列表的头部,发现相同,就进行更新复用;
- 然后比较旧节点列表的尾部和新节点列表的尾部,发现不同,记录差异;
- 接着继续比较旧节点列表的尾部和新节点列表的头部
- 依次类推,通过这种双端比较的方式来找出需要更新、移动、添加或删除的节点。
- 优势
- 这种算法在处理节点顺序变化较小的情况时比较高效。因为它能够快速地从两端定位到相同的节点,减少比较的次数。
- 缺点
- 当节点列表的变化比较复杂,比如大量节点的插入、删除或者乱序,双端比对可能需要进行多次比较才能确定节点的操作。
-
Vue 3.0 Diff 算法,基于最长递增子序列(Longest Increasing Subsequence,LIS)的优化。
- 它首先会遍历新旧节点列表,找到相同的节点并进行更新复用。
- 然后,对于那些需要移动的节点,它会通过计算最长递增子序列来确定最少的移动操作。
- 优势
- 在处理复杂的节点列表变化时,尤其是节点顺序频繁变化的情况,Vue 3.0 的 Diff 算法表现更优,降低性能开销
13、vue Data里面如果有数组,如何检测数组的变化
- 简略回答
Vue可以使用 watch 和 computed 监听数组的变化
- 详细回答
-
使用 watch 监听数组:
- 可以通过 deep 选项深度监听数组内部元素的变化。
-
使用 computed 监听数组
- 创建一个计算属性,返回数组的长度或者某个数组元素的值,当数组发生变化时,计算属性会自动更新。
14、将数组改为响应式数组
- 简略回答
- vue2中通过set方法将一个新的数组或者修改后的数组设置为响应式
- vue3中使用reactive函数,或者使用ref 函数
- reactive函数可以将一个普通对象(包括数组)转换为响应式对象。
- ref函数主要用于包装基本数据类型,但也可以用于数组。它返回一个Ref对象,通过.value属性来访问和操作数组。(将数组作为一个独立的值进行传递和使用)
- 详细回答
PS.未完待续,文中答案有误也欢迎评论指出!
另外作者也在找工作,欢迎公司有HC的同学内推,base地:上海、北京或杭州。