Vue面试题重难点总结


1. 如何实现一个路径渲染多个组件?

如何实现一个路径渲染多个组件?

2. vue-router 3.1.0 <router-link>新增的v-slot属性怎么用?

<router-link>的v-slot可以获取到底层的一些属性,用来做定制。使用v-slot时,要向router-link中传入一个单独的子元素,否则会被包裹在span中。

在这里插入图片描述

3. 如何监测动态路由的变化

如何监测动态路由的变化

4. 对MVC,MVP,MVVM的理解

对MVC,MVP,MVVM的理解

5. Vue数据响应式原理

  1. 所谓的数据响应式指的是数据变了,视图跟着变
  2. 总结成一句话:就是利用Object.defineProperty数据劫持和观察者模式来实现的
  3. vue会遍历此data中对象所有的属性,并使用Object.defineProperty把这些属性注册为getter/setter
  4. 每个组件实例都有watcher对象,watcher把在模板编译过程中所有的需要数据的对象记录下来,存在观察者列表中,并让订阅器Dep对观察者列表进行统一管理
  5. 当某个data中属性变化的时候,由于被劫持了,所以vue内部是知道的,调用对应的dep,去通知观察者列表中所有的观察者更新视图,从而致使它关联的组件得以更新。

在这里插入图片描述

6. 不用vuex时,简单的store模式管理数据

store 状态管理模式的实现思想很简单,就是定义一个 store 对象,对象里有 state 属性存储共享数据,对象里还存储操作这些共享数据的方法。在组件中将 store.state 共享数据作为 data 的一部分或全部,在对 store.state 对象里的共享数据进行改变时,必须调用 store 提供的接口进行共享数据的更改。

7. v-model和vuex有冲突吗?

v-model和vuex有冲突吗?

v-model是双向数据绑定 vue实例的data改变或者用户输入的改变都会触发视图更新。vuex是一个状态的存储,对于里面的状态的改变都是通过commit mutation 所以当用户输入直接修改editableTabsValue2,又不是通过commit更改状态时会报错。

8. 解释单向数据流和双向数据绑定

解释单向数据流和双向数据绑定

view更新data通过事件监听即可,比如input标签监听 ‘input’ 事件就可以实现了。而当数据改变,则是由于vue的数据响应式原理。

9. vue-router 路由实现原理

vue-router 路由实现原理

10. Vue-router使用params与query传参有什么区别

Vue-router使用params与query传参有什么区别

请添加图片描述

11. 说明一下封装vue组件的原则和方法

说明一下封装vue组件的原则和方法

12. 谈谈vue生命周期函数?

谈谈vue生命周期函数

el是Vue实例的挂载目标。在实例挂载之后,元素可以用 vm.$el 访问。
挂载阶段还没开始的时候,$el属性是不可见的。Vue生命周期mounted阶段,el被新创建的vm.$el替换,这个时候Vue实例的挂载目标确定, DOM渲染完毕。在这个Vue实例当中,也就可以使用vm.$el访问到el了。

13. vue的实例选项对象?

vue的实例选项对象

vue的实例选项对象

14. computed和watcher的区别?

computed和watcher的区别

15. Vue中computed的原理,怎么追踪到它的依赖的?怎么确定是他的依赖变更他才更新?

简单来说,computed 是定义在 vm 上的一个特殊的 getter 方法,之所以说特殊,是因为在 vm 上定义 getter 方法时,get 并不是用户提供的函数,而是 Vue.js 内部的一个代理函数,在代理函数中可以结合 watcher 实现缓存与依赖等功能。

计算属性的结果会被缓存,且只有在计算属性所依赖的响应式属性或者说计算属性的返回值发生变化时才会重新计算,那么如何知道计算属性的返回值是否发生变化?这其实是结合 watcher 的 dirty 属性来判断:当 dirty 属性为 true 时,说明数据已经“脏”了,需要重新计算“计算属性”的返回值,当 dirty 属性为 false 时,说明计算属性的值并没有改变,不需要重新计算。

当计算属性中的内容发生变化后,计算属性的 watcher 会得到通知,计算属性的 watcher 会将自己的 dirty 属性设置为 true,当下次读取计算属性时,就会重新计算一次值,如果发现这一次计算出来的值与上一次计算出来的值不一样,再主动通知组件 watcher 进行重新渲染操作,由于要重新执行 render 函数,所以会重新读取计算属性的值,这个时候计算属性的 watcher 已经把自己的 dirty 属性设置为 true,所以会重新计算一次计算属性的值,用于本次的渲染。

计算属性会通过 watcher 来观察它所用到的所有属性的变化,当这些属性发生变化时,计算属性会将自身的 watcher 属性设置为 true,说明自身的返回值变了。

在这里插入图片描述

16. v-for key

2. “原地复用”

“原地复用”是指Vue会尽可能复用DOM,尽可能不发生DOM的移动。Vue在判断更新前后指针是否指向同一个节点,其实不要求它们真实引用同一个DOM节点,实际上它仅判断指向的是否是同类节点(比如2个不同的div,在DOM上它们是不一样的,但是它们属于同类节点),如果是同类节点,那么Vue会直接复用DOM,这样的好处是不需要移动DOM

"原地复用"应该就是设置key和不设置key的区别:

不设key,newCh和oldCh只会进行头尾两端的相互比较,设key后,除了头尾两端的比较外,还会从用key生成的对象oldKeyToIdx中查找匹配的节点,所以为节点设置key可以更高效的利用dom

vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。

这样容易导致一些问题。因为类似 <input> , <select> , <textarea> 这样的元素都有一个internal state 保存着元素的值,而在元素复用时,这个值是会得到保留的。

我们会发现,在点击按钮切换登录方式的时候,输入框中已有的内容 不会被清除 ,这是因为input 的 internal state 保留着元素的值。

如果我们希望切换的时候不保留这个值呢?我们可以给两个 input 添加不同的 :key 。**因为 vue 是将 key 作为唯一标识从而来识别复用的元素的,**如果两个元素的 key 不同,那么就相当于告诉 vue“这两个元素是完全独立的,不要复用它们”。

17. vue的diff比对

diff算法包括一下几个步骤:

  • 用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文

档当中

  • 当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较(diff),记录两棵树差异
  • 把2所记录的差异应用到步骤1所构建的真正的DOM树上(patch),视图就更新了

diff算法有两个比较显著的特点:

  1. 比较只会在同层级进行, 不会跨层级比较。
  2. 在diff比较的过程中,循环从两边向中间收拢。

首先,我们拿到新旧节点的数组,然后初始化四个指针,分别指向新旧节点的开始位置和结束位置,进行两两对比,若是 新的开始节点和旧开始节点相同,则都向后面移动,若是结尾节点相匹配,则都前移指针。若是新开始节点和旧结尾节点匹配上了,则会将旧的结束节点移动到旧的开始节点前。若是旧开始节点和新的结束节点相匹配,则会将旧开始节点移动到旧结束节点的后面。若是上述节点都没配有匹配上,则会进行一个兜底逻辑的判断,判断开始节点是否在旧节点中,若是存在则复用,若是不存在则创建。最终跳出循环,进行裁剪或者新增,若是旧的开始节点小于旧的结束节点,则会删除之间的节点,反之则是新增新的开始节点到新的结束节点。

18. Vuex如何实现跨组件的数据监听

Vuex如何实现跨组件的数据监听

19. axios怎么封装的

import axios from 'axios'
import store from '@/store'

// 不直接使用axios对象,而且使用它创建的一个新的实例化对象
const instance = axios.create()

// 响应拦截器
instance.interceptors.response.use(
  // 解套,减少数据的调用层级
  res => res.data,
  err => Promise.reject(err)
)

// 请求拦截器
instance.interceptors.request.use(config => {
    
    
  config.timeout = 10000
  config.baseURL = 'http://localhost:9000'
  
  // 在请求拦截器中对所有的请求添加 token 请求字段,当然除 /api/login请求地址外
  // headers Authorization:' xxddflefewlfewj'
  config.url != '/api/login' ? (config.headers.token = store.getters.token) : null
  return config
})

/**
 * get请求
 * @param {string} url 请求的url地址
 * @param {object} config 额外的表求头信息的补充,可选
 * @returns Promise
 */
export const get = (url, config = {
     
     }) => instance.get(url, config)

/**
 * post请求
 * @param {string} url 请求的url地址
 * @param {object} data 请求体数据,可选 例:{id:1,name:'aaa'}
 * @param {object} config 额外的表求头信息的补充,可选
 * @returns Promise
 */
export const post = (url, data = {
     
     }, config = {
     
     }) => instance.post(url, data, config)

20. Vue虚拟DOM

虚拟 DOM (Virtual DOM )这个概念相信大家都不陌生,从 ReactVue ,虚拟 DOM 为这两个框架都带来了跨平台的能力(React-NativeWeex

实际上它只是一层对真实DOM的抽象,以JavaScript 对象 (VNode 节点) 作为基础的树,用对象的属性来描述节点,最终可以通过一系列操作使这棵树映射到真实环境上

Javascript对象中,虚拟DOM 表现为一个 Object对象。并且最少包含标签名 (tag)、属性 (attrs) 和子元素对象 (children) 三个属性,不同框架对这三个属性的名命可能会有差别

创建虚拟DOM就是为了更好将虚拟的节点渲染到页面视图中,所以虚拟DOM对象的节点与真实DOM的属性一一照应

vue中同样使用到了虚拟DOM技术

Vue为什么要使用虚拟Dom?

用传统的开发模式,原生JS或JQ操作DOM时,浏览器会从构建DOM树开始从头到尾执行一遍流程。在一次操作中,我需要更新10个DOM节点,浏览器收到第一个DOM请求后并不知道还有9次更新操作,因此会马上执行流程,最终执行10次。例如,第一次计算完,紧接着下一个DOM更新请求,这个节点的坐标值就变了,前一次计算为无用功。计算DOM节点坐标值等都是白白浪费的性能。即使计算机硬件一直在迭代更新,操作DOM的代价仍旧是昂贵的,频繁操作还是会出现页面卡顿,影响用户体验。

Web界面由DOM树(树的意思是数据结构)来构建,当其中一部分发生变化时,其实就是对应某个DOM节点发生了变化,虚拟DOM就是为了解决浏览器性能问题而被设计出来的。如前,若一次操作中有10次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地一个JS对象中,最终将这个JS对象一次性attch到DOM树上,再进行后续操作,避免大量无谓的计算量。所以,用JS对象模拟DOM节点的好处:页面的更新可以先全部反映在JS对象(虚拟DOM)上,操作内存中的JS对象的速度显然要更快,等更新完成后,再将最终的JS对象映射成真实的DOM,交由浏览器去绘制,从而提高性能。

21. Vnode的缺点

  • 首次显示要慢些:
    首次渲染大量DOM时,由于多了一层虚拟DOM的计算, 会比innerHTML插入慢
  • 无法进行极致优化
    虽然虚拟 DOM + 合理的优化,足以应对绝大部分应用的性能需求,但在一些性能要求极高的应用中,无法进行针对性的极致优化。

22. nextTick知道吗?实现的原理是什么?是宏任务还是微任务?

nextTick知道吗?实现的原理是什么?是宏任务还是微任务?

23. 介绍下vue父子组件生命周期的执行顺序

在这里插入图片描述

24. Vue的常用修饰符

Vue的常用修饰符

25. Vue中子组件是否可以修改props,如果想修改的话如何修改

  1. v-model绑定到自定义组件中
  2. sync同步动态属性数据
  3. $emit()
  4. 父组件直接把修改数据的方法以属性的方式传给子组件(通过形参方式传递)

Vue中子组件是否可以修改props,如果想修改的话如何修改

26. Vue中 router-link 和传统 a 链接的区别?

Vue中 router-link 和传统 a 链接的区别

27. 什么是 Vue.js 动态组件与异步组件?

什么是 Vue.js 动态组件与异步组件

28. v-show与v-if的区别

  • 控制手段不同
  • 编译过程不同
  • 编译条件不同

控制手段:v-show隐藏则是为该元素添加css--display:nonedom元素依旧还在。v-if显示隐藏是将dom元素整个添加或删除

编译过程:v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;v-show只是简单的基于css切换

编译条件:v-if是真正的条件渲染,它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。只有渲染条件为假时,并不做操作,直到为真才渲染

  • v-showfalse变为true的时候不会触发组件的生命周期
  • v-iffalse变为true的时候,触发组件的beforeCreatecreatebeforeMountmounted钩子,由true变为false的时候触发组件的beforeDestorydestoryed方法

性能消耗:v-if有更高的切换消耗;v-show有更高的初始渲染消耗;

猜你喜欢

转载自blog.csdn.net/weixin_45605541/article/details/127464925