Vue 求职无忧含答案

1、Vue 中 v-if 和 v-show 都有什么区别?如何使用?

  • v-if 和 v-show 都是用来控制 DOM 元素 或 组件 在页面是否显示。
  • v-if 是直接添加或删除对应 DOM 元素 或组件,如果是组件,添加过程中会触发组件内部的生命周期,如果在运行时条件很少改变,则使用 v-if 较好。
  • v-show 是使用 css 属性 display:none进行显示或者隐藏控制,不删除元素,不触发组件生命周期,如果需要频繁切换,使用 v-show 较好,降低性能消耗。

2、Vue 中 data 视图更新是同步的还是异步的?谈谈你的理解?

  • Vue 数据更新分为两步,JS 中更新数据 是同步的,触发 DOM 更新是异步的。
  • JS 同步更新数据会进行依赖采集,多次合并为最后一次,再进行 DOM 异步更新,避免了频繁的更新 DOM, 提高了性能。
  • 如果视图更新完成后,需要进行操作,可以使用 $nextTick 进行后续操作。

3、谈谈你对 Vue 中 nextTick 的理解,它和 setTimeout 有什么区别?

  • Vue 更新 DOM 是异步操作,如果我们需要拿到 更新后 的 DOM 结构,可以使用 $nextTick 进行后续操作,确保拿到更新的 DOM 结构。
  • 使用 nextTick 很简单,就是传入一个回调方法就可以了
  • nextTick 会先尝试使用 promise 微任务来进行调用,如果都不行,才会使用 setTimeout 进行宏任务调用。

PS:什么是宏任务?什么是微任务?

4、Vue 中都有哪些常用的修饰符?谈谈你的使用和理解?

  • vue 中的修饰符有表单修饰符、事件修饰符、鼠标按键修饰符、键盘别名修饰符 等
  • 事件修饰符,常用的有 stop 阻止事件冒泡,prevent 阻止默认行为 等
  • 表单修饰符,常用的有 lazy 失去焦点触发,trim 祛除首尾空格,number 强制数据输入等
  • 鼠标修饰符,常用的 left,right,middle
  • 键盘修饰符,常用的 上下左右、回车等别名

5、谈谈你对 Vue 中 this 对象的理解,如何确保 this 指向 Vue 实例化对象?

  • Vue 中 this 对象一般就代表当前 组件的实例化对象
  • 在定时器、axios 等异步回调中,我们可以使用 that 来暂存,或者使用箭头函数来确保 this 指向到当前实例。

6、computed 和 watch 有什么区别?一般你都在什么地方使用?

  • computed 用于对响应式变量进行二次计算,当它依赖的响应式变量发生变化时会自动重新计算,需要返回一个新的值,直接在模板中使用。
  • watch 用于监听响应式变量的变化,针对某个响应式对象的变化,追加我们的业务逻辑使用。

7、Vue 中都有哪些获取、操作、更新 DOM 的方法?

  • 我们一般不推荐在 Vue 中直接操作 DOM,特殊情况下,我们可以使用 ref 或者 自定义指令来获取操作 DOM节点。
  • 使用 ref 获取 DOM 元素,Vue2 中使用 字符串标注,然后使用 $refs.名字 获取,Vue3 中 createRef Hooks 创建对象,绑定到对应的 DOM 元素。
  • 自定义指令,有三个对应的钩子函数 bind、inserted、updated,钩子函数自动接收的参数就是当前 DOM 对象。

8、使用过 Vue 的自定义指令吗?谈谈你对它的理解?

  • 当我们在项目中需要对某些 dom 进行定制化操作的时候,就可以使用到自定义指令。
  • 自定义指令注册分为 全局注册 或 局部注册 两种方式,使用直接像普通的 vue 指令 v-自定义指令名
  • 自定义指令,有三个对应的钩子函数 bind、inserted、updated,钩子函数自动接收的参数有当前 DOM 对象、绑定的数据等。一般情况下,我们可以使用简写的方式直接回调一个方法就可以了。

9、Vue 中 v-if 和 v-for 同时使用的弊端?如何解决这个问题?

  • v-if 是通过创建和销毁元素来控制显示隐藏的,然后v-for的级别比v-if的级别高,就导致每循环一次就要v-if一遍,会造成页面的卡顿,性能消耗大
  • 解决方法:在 computer属性里面过滤了数据,再使用v-if,或者在 v-for 内层,包裹一个元素用来使用 v-if

10、谈谈你对 Vue 过渡动画效果实现的理解和使用?

  • 在 Vue 中不能直接使用 js 来操作 DOM 实现动画,需要配合 CSS3 的过渡或者动画属性操作来实现动画效果,所以,我们也叫做 Vue 过渡动画。
  • Vue 过渡动画分为两种,第一种为 单个元素动画,使用 transition 标签包裹, v-if/show 切换显示状态触发;第二种为 分组元素动画,使用 transition-group 标签包裹,对数组元素动态的添加或者移除,来进行控制。
  • 过渡动画在控制中,会区分进入或者离开两种场景,动态的添加或者移除 6 个 className,进入前、进入中、进入后,离开前、离开中、离开后。
  • 在我之前的工作中,过渡动画用的并不是特别多,用到几次也是配合 animate css 动画库。

11、谈谈你对 MVVM 框架的理解?

  • MVVM 是一种软件架构设计模式,可拆分为 Model-View-ViewModel
  • Model是数据模型,对应开发时的 JS 数据,比如 data 中声明的数据
  • View 是视图层,对应开发时的 DOM 结构,template 模板内容
  • ViewModel 是 Model 与 View 的中间层,负责处理交互逻辑,数据更新时视图能更新,视图更新数据也能更新。

12、什么是虚拟 DOM?在 Vue 中为什么使用 虚拟 DOM?

  • 虚拟 DOM 本质上来讲,就是 使用 js 对象来描述 DOM 结构,可以用来渲染成为真实 DOM,这样的话,就可以让 Vue 框架具有了 跨平台的能力。

  • 同时 在 Vue 中使用虚拟 DOM,也有两个具体的优势:

    第一个是 响应式对象数据修改到 DOM 更新这个操作过程是一个异步操作,虚拟 DOM 可以进行依赖采集,避免过于频繁的真实 DOM 操作,提高性能。

    第二个是 虚拟 DOM 去修改 真实 DOM 的过程中,基于 diff 差异化比较算法,只更新需要更新的部分,进一步的提高性能。

13、谈谈你对 虚拟 DOM 和 diff 算法的理解?

  • 虚拟 DOM 本质上来讲,就是 使用 js 对象来描述 DOM 结构,可以用来渲染成为真实 DOM,我们也可以理解为 js 和真实 DOM 中间的一个缓存区,这样的话,就可以让 Vue 框架具有了 跨平台的能力。

  • diff 算法就是 对 虚拟 DOM 进行差异化比较的算法,比较的过程有两个关键特性。

    第一个是 响应式对象数据修改到 DOM 更新这个操作过程是一个异步操作,虚拟 DOM 可以进行依赖采集,避免过于频繁的真实 DOM 操作,提高性能。

    第二个是 虚拟 DOM 去修改 真实 DOM 的过程中,基于 diff 差异化比较算法,只更新需要更新的部分,进一步的提高性能。

14、说说 Vue 中为什么要使用 Key 值?

  • 在 Vue 的 for 循环或者 组件调用的时候,可以添加一个 key 属性,简单来说,就是用来进行标识的。
  • 在 for 循环中,使用 key 值,可以配合 diff 算法精准的定位 添加或者移除的 节点元素,不需要全量更新,只需要局部更新就可以了,这样可以大大的降低性能消耗。
  • 给组件添加一个 key 属性,当 key 值发生变化的时候,可以重新触发整个组件的 销毁和重新创建,可以追加一些我们需要的逻辑。

15、Vue 双向数据绑定 v-model 的原理是什么?观察者模式?

  • v-model 也叫做 双向数据绑定,本质上讲是一个语法糖,监听表单的 input 输入事件,对其 value 值进行动态绑定,最终实现双向数据绑定的效果。
  • vue 的双向绑定是由 数据劫持 结合 发布订阅 模式实现的。
  • 数据劫持 就是通过 Object.defineProperty() proxy()来劫持对象属性的 setter 和 getter 操作,在数据变动时做你想要做的事情 。
  • 发布订阅 就是 发布者 Observer,用来监听所有属性,如果属性发生变化了,就需要告诉订阅者 Watcher 看是否需要
  • 更新。订阅者是有多个,所以 我们使用 一个消息订阅器来专门收集这些订阅信息,然后再交给发布监听者 Observer 和订阅者 Watcher 之间进行统一管理的。

16、结合日常使用场景,谈谈你对 Vue 生命周期的理解?

  • 生命周期简单来说就是 回调的钩子函数,Vue 实例从创建到销毁的过程中,不同的时机可以追加不同的业务逻辑。

  • 生命周期分为 挂载、更新、销毁三个阶段,挂载阶段有四个钩子函数,beforecreated,created,beforemounted,mounted;更新阶段 beforeupdate,updated;销毁阶段有 beforedistroy 和distroyed。

  • 我们常用的生明周期钩子函数

    created 发出默认的数据请求,因为这个时候响应式数据对象已经实例化了

    mounted 获取 DOM 节点,因为这个时候 虚拟 DOM 已经解析成了 真实 DOM

    updated 监听了所有响应式对象数据,我们用的比较少,使用 computed 或者 watch 更好

    beforedistroy 可以将可能造成内存泄漏的 异步操作进行垃圾回收,比如 计时器等

17、谈谈你对 Vue mixins 混入的理解?日常工作为什么不推荐使用 mixins?

  • mixins 混入,就是对多个组件需要共享 响应式对象数据、生命周期、事件方法等的时候,我们可以进行 mixins 抽离封装,提高代码的复用性。

  • mixins 混入在调用的时候,对应的 响应式对象数据、事件方法等,可以被重新声明,新的声明会覆盖mixins 声明。但是,生命周期 created 和 mounted 不会被复写,会被追加逻辑。

  • mixins 从程序设计角度来讲,不符合代码高内聚、低耦合的特性,多人协作的时候,冲突操作会比较多,所以,在 Vue3 中取消了 mixins。

    高内聚,就是 模块化的功能尽量集中在模块内部,不要依赖模块外部;低耦合,就是不同的模块之间互相不要互相依赖,每个模块都是单独的存在。

18、Vue 中组件的 data 为什么必须要使用 函数声明?

  • Vue 组件是可以被重复调用的,如果组件中的 data 是一个函数的话,这样每调用一次组件,就会返回一份新的 data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。
  • 如果,我们写成了对象形式,就使得所有组件实例共用了一份 data,就会造成一个变了全都会变的结果,造成数据污染。

19、axios 和 ajax 有啥区别?axios 常用的封装有哪些?

  • ajax 是 jQuery 框架的一个功能,依赖 jQuery 框架,核心是 基于 XMLHttpRequest 进行封装实现的。
  • axios 是一个独立的单独用来发送网络请求的 插件,不依赖于任何框架,axios 并且进行了 promise 封装,避免 回调地狱,可以使用 async await 非常方便的使用。

20、模板引擎的概念你理解不?谈谈 Vue 模板编译的过程理解?

  • 理解!
  • 简单来说,我们所写的 Vue 代码都是 一段 字符串,在 template 里面有很多 Vue 指令,比如 v-for v-if v-bind v-model 等,这些指令不是标准的 HTML 语言结构,是无法被 浏览器直接解析的。
  • 这个时候,我们就需要使用类似 正则替换 等方式,对我们写的代码进行 编译解释,成为 浏览器可以运行的标准 HTML 结构的过程,这就是模板引擎解析。

21、谈谈 Vue 中父子、子父、兄弟之间、祖父与孙子节点同通信的方法?

  • 组件通信就是组件之间传递数据的方法,主要分为四大类,父子通信、兄弟通信、祖父孙子通信、非关系组件通信。
  • 父传子:父组件内部设置自定义属性,子组件内部基于 props 接收即可,可以设置默认值。
  • 子传父:父组件定义自定义事件名,子组件 $emit 模拟触发父组件传递的自定义事件名,可以传递参数。
  • ref 绑定组件:获取子组件最高权限,直接操作子组件属性和方法,实现通信,不推荐使用。
  • EventBus:中央事件总线 $on 声明一个自定义事件,$emit 触发该事件,实现通信,可以传递参数,Vue3 中没有 this 使用 mitt 插件替代。
  • provide 与 inject:数据供应和数据消费,在祖先组件上声明数据供应,在子孙组件中获取数据消费。
  • Vuex: 全局状态管理,唯一数据源,整个应用方便的读取和操作,并且有响应式效果。

22、谈谈你对 Vue 插槽的理解?具体的分析一下什么是作用域插槽?

  • Vue 插槽是父组件向子组件传递 HTML 结构的方法,有默认插槽、具名插槽、作用域插槽三种形式。
  • 作用域插槽是一种特殊类型的插槽,结构样式父组件说了算,但父组件中需要的数据子组件说了算,使用 v-slot 名称或者#name来获取即可。
  • 在 饿了么 UI 中,比如 表格 行列数据等维度经常使用到 作用域插槽。

23、Vue 有三个核心概念,数据驱动、渐进式、组件化,谈谈你的理解?

  • 数据驱动,简单来说就是 修改 JS 中的数据,会自动驱动 页面 DOM 更新,开发者不需要关注 DOM 层,只需要关注 数据的操作,就可以完成开发。
  • 渐进式,简单来说就是 Vue 开发不是一次性将 axios Vuex Router 等一股脑的都用上,需要用到什么,咱就使用什么,一步一步的增加功能就是 渐进式。
  • 组件化 是一种复用思想,可以将大的页面进行模块化的分割,一方面方便了代码的开发阅读便捷性,一方面对于可能多处复用的功能进行逻辑复用。

24、你都做过哪些 Vue 的性能优化?

  • 对消耗网络资源的文件,进行懒加载和预加载配合。
  • 对于大型项目,使用 路由懒加载,提高首屏访问速度。
  • 在按钮点击或者页面滚动等频发操作时进行节流和防抖。
  • 第三方组件库组件或插件按需引入,减少打包体积。
  • 使用 keep-alive 缓存页面,获取更好的页面反复切换体验。
  • 在 v-for 的时候,避免使用 v-if 操作,可以使用计算属性进行过滤。
  • 对于页面中的类似计时器、无效事件等,在页面销毁的时候,手动回收,避免内存泄漏。
  • 在打包的时候,开启代码压缩功能,确保打包的代码体积尽可能降低。

25、谈谈你对 Vue 过滤器的使用理解?

  • Vue 过滤器,就是在不改变原数据的前提下,对数据进行需要的格式化处理,再返回并显示在页面上 。
  • 过滤器,可以进行全局声明也可以进行局部声明,使用 | 管道符进行调用即可。
  • 在 Vue3 中直接调用声明的方法,传入需要格式化的数据,也可以实现效果,所以就取消了过滤器。

26、Vue 的 $set 是什么?都有什么用?

  • vue 中的 $set 用来更新数组或对象,用于解决数据修改后视图不更新的问题。
  • $set 接受三个传参,第一个是需要更新的数组或者对象,第二个为下标或者键值,第三个为需要修改的值
  • Vue3 使用 proxy 进行数据监听,自身就可以监听数组或者对象的内部,就取消了 $set。

27、谈谈你对前端路由原理的理解?hash 和 history 的实现原理介绍一下?

  • 前端路由,简单的来说就类似于一个高等级的 tab 选项卡,根据我们的操作,动态的显示和隐藏 对应的页面。
  • 当然,前端路由不是监听用户 点击事件,监听的是 路由地址变化的事件。
  • 路由地址的变化事件,有两种形式,一个是监听 hash 值变化,一个是监听 HTML5 history 地址的进栈和出栈操作,这两种形式也对应 Vue 两种路由模式 hash 模式 和 history 模式。

28、简要介绍 VueRouter 的实现步骤?

  • 第一步,安装路由依赖包,并导入。
  • 第二步,声明路由文件,导入路由配置文件。
  • 第三步,声明路由规则,包含路径、子路由、动态路由等等。
  • 第四步,创建路由实例并导出。
  • 第五步,Vue use 注入路由依赖文件规则。
  • 第六步,使用 router-link 声明式导航或者 router.push 编程式导航调用路由。
  • 第七步,使用 router-view 占位接收路由对应的页面。

29、在 Vue 路由中传参都有哪些方法?

  • Vue 路由传参是不同页面之间传递数据的方式,主要有三种方式
  • 第一种,我们最常用的 动态路由 传参,也叫做 params 显式传参,在 url 地址中直接显示数据,刷新页面后数据不会丢失。
  • 第二种,使用 query 传参,在 url 地址上,使用 ?后面拼接的方式显示传递数据,刷新页面数据不会丢失。
  • 第三种,params 隐式传参,不在 url 地址栏上显示,刷新页面会丢失,Vue3 也已经取消了这种方式。

30、VueRouter 路由懒加载如何实现?

  • 路由懒加载也叫延迟加载,即在需要的时候进行加载,避免不必要的消耗。
  • 路由懒加载的实现原理,简单来说,就是根据需要,在路由切换到对应页面的时候,动态的 创建一个 script 标签,再给它设置一个 src 属性,按需完成页面加载效果。

31、谈谈 VueRouter 中 route 和 router 区别?

  • route 和 router 是 Vue 路由操作中经常会操作的两个对象, 用一句话来概括这两个的区别,就是 route 是用来获取路由信息的,router是用来操作路由的
  • route 表示当前的路由信息对象,包含了 当前 URL 解析得到的信息,包含当前的路径、参数、query对象等,一般用于获取跳转时传入的参数。
  • router 对象是全局路由的实例,是router构造方法的实例,一般用户路由跳转,如 router.push() 、 router.replace() 等方法

32、路由守卫是什么?一般你都是怎么使用的?全局和局部使用的差异是什么?

  • 路由守卫就是路由跳转前、后过程中的一些钩子函数,可以让我们在页面跳转之前或之后,进行一系列的操作,限制路由的跳转。
  • 路由守卫分为:全局守卫、单个页面局部守卫,路由守卫钩子函数可以接收三个参数,to 到哪里去,from 从哪里来,next() 放行方法。
  • 全局守卫,一般写在路由配置文件中,整个应用任意跳转都会生效,有三个钩子函数 beforeEach、afterEach、beforeResolve
  • 单个页面局部守卫,直接写在当前页面组件内部,和其他生命周期钩子函数一样,只有当前页面跳转逻辑中会生效,有三个钩子函数:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
  • 我们使用比较多的,是通过路由导航守卫,来对管理员进行访问权限控制,只有管理员具有访问当前路由的权限才允许其访问。

PS:我们可以对当前管理员的权限进行页面级别的配置操作,保存到数据库中,当前用户登录后,获取到权限,解析路由可访问的具体页面。

33、什么是动态路由?什么是嵌套路由?谈谈你的理解和使用?

  • 动态路由,就是动态的拼接路由,一般用来进行 params 传参使用,所有路由地址都对应的是一个路由页面组件,根据不同的参数,请求或渲染不同的数据。
  • 嵌套路由,就是子路由,每个子路由地址都会对应自己独立的路由页面,在使用的时候,需要注意在父路由中使用 router-view 进行占位显示,子路由规则声明的时候,不要使用 / 这个要注意。

34、有没有在 Vue 按需动态创建过路由地址?谈谈你的理解和使用?

  • 使用 new VueRouter、createRouter 直接创建好路由地址表,这个表一经创建就固定了,我们也叫做 静态的路由地址表。

  • 动态创建路由, router.addRoutes()方法实现, 简单的来讲就是 不在初始化就创建好路由规则表,而是根据条件,动态的创建路由规则表,主要用来对不同权限角色进行不同的路由规则表生产过程。

  • 根据用户的不同权限来渲染不同的路由地址的几种方案:

    第一种:可以配合路由导航守卫,来根据不同的权限去调用不同的页面,没有权限就进行拦截跳转;

    第二种:可以调用路由的一个 api 方法 router.addRoutes({ 路由规则 }) 动态的添加路由,如果没有权限,直接这个路由就不存在。

    • 如果权限不是很复杂,不需要后台动态的手动配置,直接前端写好变量,选择配置。
  • 如果权限要求比较高,需要后台动态配置各种操作,权限存储在数据库中。

35、SPA 单页面应用是什么?与 MPA 多页面应用有什么区别?有什么优缺点?

  • SPA,即单页面应用,所谓单页面应用,就是只有一张 Web 页面的应用。也就是,浏览器一开始就会加载所有的 HTML、CSS 、JS,所有的操作都在这张页面上完成,都由 JS 来控制。
  • MPA,即多页面应用,指有多个独立的页面的应用,每个页面必须单独完全加载自己的 HTML、JS、CSS 等相关资源,有后端路由控制不同的服务器资源来进行控制。
  • SPA 应用一次性加载了所有资源,就像是访问 原生 APP 一样顺滑,但是,首次加载需要把所有的资源都一次性下载下来,首屏等待时间会比较长,当然,我们也可以使用 路由懒加载、骨架屏等解决方案来解决这个问题。
  • SPA 所有的内容都在 JS 中控制,不利于 SEO 搜索引擎获取内容,MPA 直接渲染输出 HTML 内容结构,有利于 SEO 获取内容。但是,MPA 每个页面切换都会重新请求资源内容,体验没有 SPA 顺滑!

36、对 keep-alive 的理解,它是如何实现的,具体缓存的是什么?keepAlive 生命周期有哪些?

  • 在 vue 项目中,每次组件切换的时候上一个组件都会被销毁,那你要是想访问上一个组件,就得重新渲染,那 keep-alive的作用主要就是用于保存组件的状态避免重新渲染,提高性能。
  • 一般应用场,比如搜索一个列表页面,返回的时候不想它回到初始状态,还想要之前的搜索结果,那就用到 keep-alive 就可以了。
  • keep-alive 会比平常的组件多两个生命周期钩子函数,分别是:activated 激活显示缓存页面时触发,deactivated 离开显示缓存页面时触发。

37、Vuex 的核心概念理解?为什么要用 Vuex?

  • Vuex 叫做 状态管理,解决多个组件、页面共享数据的问题,方便整个应用进行统一管理,随时读取和操作唯一数据源 state。
  • state 数据是 响应式动态数据,修改了 state 数据,会驱动整个应用所有使用的地方更新数据。
  • 修改 state 数据的规则,需要提前声明在 mutation、action 中,保证了状态可预测变化。
  • 需要注意的是,Vuex 在刷新的时候会恢复初始化设置数据,我们需要配合 sotrage 缓存使用。

38、Vuex 的原理? Vuex 和单纯的全局对象有什么区别?

Vuex 和 localStorage 区别?

  • vuex 状态管理,是应用于 vue.js 中管理数据状态的一个库,通过创建一个集中的数据存储,供程序中所有组件访问,实现组件之间的传值,并且一个组件的数据变化会映射到使用这个数据的其他组件。

  • 它与全局对象的不同:

  • vuex 由统一的方法修改数据,全局变量可以任意修改,很难被控制。

  • 全局变量多了会造成命名染,Vuex 不会,Vuex 内部唯一数据源 state 声明非常干净。

  • 它与 localStorage 的不同:

    • vuex 存储在内存,localstorage 以文件的方式存储在本地。
    • localstorage 只能存储字符串类型的数据,储存对象需要 JSON 的 Stringify 和 parse 方法进行处理,Vuex 可以存储复杂数据类型。
    • vuex 能够做到数据的响应式,localstorage 不能。
    • 刷新页面时 vuex 存储的值会丢失,localstorage 不 会。

39、Vuex 的状态是一个对象或者数组使用需要注意什么?

  • 对象或者数组是 引用数据类型,在栈内存中以指针的形式存在。
  • 如果修改了 对象中的某个属性 或者 修改了 数组中的 某个元素 ,并不会触发整个对象、数组的指针变化,所以需要注意,在 Vue2 中,修改了对象属性 或 数组元素后,可以使用 … 拓展运算符,或者 Object.assign ,或者使用 json 字符串转换 js 对象浅拷贝逻辑,等方法确保指针发生变化,进而触发 页面 DOM 更新状态变化。

40、Vuex 有哪几种属性?action 和 mutation 的区别?

为什么 Vuex 的 mutation 中不能做异步操作?

  • Vuex 进行全局状态管理,配置的时候 主要有 5 个具体的属性,state 唯一数据源,不允许直接修改;mutations 同步修改 state 数据,并且会在 devtools 工具上产生对应的修改记录;actions 异步修改数据,调用 mutations 声明的方法进行修改;getters 类似计算属性,对 state 中的数据进行二次计算,直接使用;module 分模块操作。
  • Vuex 中状态更新的途径简单来说,只能通过 mutation 同步修改,异步操作是通过 Action 来提交 mutation 实现,这样使用的好处就是,可以使得我们借助 devtools 开发者工具来方便地跟踪每一个状态的变化。
  • mutation 中不能进行异步操作,核心目的很简单,就是确保 状态的修改 时间线的 准确性,方便调试细节数据流。每个 mutation 执行完成后都会对应到一个新的状态变更,这样 devtools 就可以打个快照存下来,然后就可以实现时间旅行记录 time-travel 了。如果 mutation 支持异步操作,就没有办法知道状态是何时更新的,无法很好的进行状态的追踪,给调试带来困难。

41、mapStates、mapMutations、mapActions 都是如何使用的?

  • mapStates、mapMutations、mapActions 是在 Vue 中方便我们快速读取 state 值,操作 mutation 、actions 方法的,可以理解为就是一个便捷的工具。
  • 在 computed 计算属性
  • 中使用 拓展运算符 直接读取 mapStates 值,直接用。
  • 在 methods 方法中,使用 拓展运算符 直接调用 mapActions ,方法直接用。

42、如何管理多个 Vuex 数据仓库?

  • 使用 moduls 模块划分,对应拆分多个数据仓库文件,比如:我们可以把用户相关模块放入 user 中, 购物车信息相关模块放入 cart 中。
  • 在调用 多模块的 state 属性、actions 方法的时候,需要当前 module 的属性后再进行追加属性调用,this.$state.user.xxx 会多一个层级。

43、Vuex 做数据请求刷新页面,数据可能会发生丢失这个问题怎么解决?

  • 因为 store 里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载 vue 实例,store 里面的数据 就会被重新赋值初始化。
  • 所以我们可以在修改 store 的数据同时将数据再存一份到本地存储 localStorage 或者 sessionStorage,本地 存储的内容是存在浏览器里面的,不会因为刷新而丢失。
  • 我们也可以使用专门的第三方插件,来帮助我们做 vuex 的持久化数据。

44、Vue 中 scoped css 作用域的实现你是如何理解的?

  • 增加了 scoped 属性的 css 样式只在当前模块作用域下生效,其他模块就算是使用了 同样的 className 也无法生效
  • 实现原理比较简单,加了 scoped 属性后,Vue 会给每个标签上新增一个自定义的属性标识,然后再通过追加对应的 css 属性选择器,确保只在当前作用域生效。

45、说一下你在使用 element ui 的时候都遇到过哪些坑?你都是如何解决的?

  • 目前使用 ElementUI 仓库的话,感觉已经很成熟了,遇到的坑并不多,现在就更少了!
  • 目前几乎没有什么印象,具体的坑,当然,开发中解决各种 Bug 倒是不少,都是 具体问题具体对待!

46、高度定制化的 ui,你是如何修改 element ui 内部组件的样式?

  • 我们可以 不使用 scoped 进行限制,使用 全局样式声明,通过选择权重覆盖 elementUI 组件的样式,但这种方式为全局样式,会影响页面中所有组件相关内容,如果不希望影响其它页面的样式,可以采用第二种方式
  • 在具体的页面上,如果是 css 选择器,添加 >>> 三个 箭头选择;如果是 scss less 预处理,使用 /deep/ 进行样式穿透,实现对应的效果。

47、开发过程中遇到跨域问题,vue-cli 是如何配置跨域的?

  • 开发过程中,因为同源策略会导致跨域的问题。我们开发中,解决的话主要有以下两个式:
  • 第一个是:在 脚手架中配置反向代理服务器,配置在 vue.config.js 的 proxy 属性上就可以了,这个也是我们最常用的方式,原理也很简单,服务器和服务器之间是没有跨域这个问题的,最终浏览器访问的是脚手架代理的服务器中转的接口数据。
  • 第二个方法,就比较单刀直入,直接跟 后端小伙伴沟通,让他们 配置一个 CORS 允许访问的策略。

48、谈谈对 webpack 中 vue-loader 的理解,实现原理是什么?

  • 浏览器只能识别普通的html、css、js,但是,Vue 写在 .vue 后缀的单文件中,内部的 模板、指令、样式等是无法被浏览器直接识别的,所以,我们就使用 vue-loader 来对 单文件进行 编译,再交给浏览器显示。

  • vue-loader 的工作流程, 简单来说,分为以下几个步骤:

    • 首先将一个 .vue 单文件 切割成 模板 template、脚本 script、样式 styles 三个部分。
  • 模板 template 部分,通过 Vue 内置的模板解析引擎 对其 指令 等进行解析。

  • 脚本 script 部分,给 模板提供 状态数据、回调方法等,配合模板引擎解析。

  • 样式 styles 部分,会通过对应的 loader 解释器,压缩后添加到 head 中,成为标准样式。

49、Vue2 和 Vue3 两者区别有哪些?Vue3 都有什么更新?

  • Vue2 使用 options api,通过配置 Vue 对象实例化需要的参数,实现业务逻辑;Vue3 使用 Composition api 借助相应的 Hooks 实现业务逻辑。
  • Vue2 使用 Object.definepropert() 对数据进行劫持 结合发布订阅模式来实现双向数据绑定;Vue3 中使用了 ES6 的 proxyAPI 对数据进行处理。
  • Vue3 新增了一个 setup 方法,在组件初始化构造的时候触发,替代了 create 相关生命周期。
  • Vue3 取消了 eventBus 事件中心,可以使用 mitt 插件进行替代。
  • Vue3 可以一定程度上 向下兼容 Vue2 的语法实现,这也是一个非常友好的操作,方便我们重构项目。
  • Vue3 使用 TS 写的,具有更好的 TS 语法特性支持。
  • Vue3 新增了 watchEffect 函数,可以更多维度的监听响应式数据对象逻辑。
  • Vue3 新增可以支持 瞬移组件 Teleport 和 异步组件 Suspense。
  • Vue2 必须有一个根节点包裹模板,Vue3可以拥有多个根节点,支持碎片(Fragments)。

50、Vue3 放弃 defineProperty,使用 Proxy 的原因?

  • definePropetry 和 Proxy 都可以对数据进行劫持,用来做响应式对象监听。
  • 但是,definePropetry 只能监听到 引用类型的指针变化,Proxy 可以监听到 对象的一级属性、数组的一级下标 变化状态。

51、谈谈 Vue3 中的 Vue Composition API 的理解?

  • 没有 Composition API 之前, Vue2 相关业务的代码,都需要配置到 option 的特定的区域,分别在data、methods、computed 里修改 ,当业务逻辑和功能越来越多的时候,理解和维护都会很复杂,虽然在中小型项目开发中问题不是很突出,但是在大型项目中,代码可复用性不高,问题就比较突出了。
  • Vue3 中的 composition-api 可以非常有效的解决这个问题。组合式 API 将每个功能点,都独立的抽象成为干净的 纯函数 Hooks,这样,就使我们可以更加优雅的组织我们的代码,让相关功能的代码更加有序的组织在一起。

52、谈谈 Vue3 异步请求组件的逻辑和使用?

  • 异步组件 就是 按需加载组件,提高用户的访问体验。
  • vue3 中使用了 Suspense 函数,来实现异步组件。实现原理很简单,Suspense 有两个 template 插槽,第一个 default 代表异步请求完成后,显示的模板内容,第二个 fallback 代表在加载过程中,显示的模板内容。

53、Vue3 中 ref、reactive 绑定数据都有什么区别?

  • Ref 的实现原理和 reactive 有一定的差异。

  • ref 用来创建响应式数据对象,如果这个响应式数据对象是 基本数据类型,内部响应式依然是靠 defineProperty 的 get 与 set 完成的。如果这个响应式数据对象是 引用类型,通过 proxy 实现。

  • reactive 所有的 类型都是通过 Proxy 数据劫持,来实现响应式。

  • ref 定义的数据,操作数据需要 .value,读取数据时模板中不需要 .value 直接使用即可。

    reactive 定义的数据,操作数据与读取数据,均不需要.value。

54、Vue 项目开发中,首屏加载空白的解决方案?

  • 首屏加载空白,是因为 SPA 应用把大量的内容都打包在了一起,网络不太好的环境下,就会出现空白等待现象,解决方案可以有很多维度。
  • 可以使用 loading 或者 骨架屏 来先进行视觉占位,加载完成后再渲染,提高用户访问友好性。
  • 可以使用 Gzip 压缩打包后的 代码大小,加快加载速度。
  • 可以使用 路由懒加载 来降低打包的体积。
  • 可以使用 SSR 服务器渲染解决方案,不再使用 SPA 渲染应用,每个页面独立渲染。

55、Vue 要做权限管理怎么做?如果控制到按钮级别的权限怎么做?

  • 权限管理 一般都分为 三个维度,应用层面、路由层面、按钮层面。

  • 应用层面一般说的是后台管理系统,如果未登录状态,除登录注册外,所有的路由禁止访问,可以使用 全局路由导航守卫实现,同时,所有的接口都不设置 Token 值进而无法访问,实现应用层面的权限控制。

  • 路由层面,一般是登录到了后台管理系统后,根据当前的用户权限,来进行路由访问能力分配。

    一般有两种方法,一种是使用全局导航守卫,接收后端返回的路由权限后,和写好的 Routes 路由规则进行比对,有权限就进入,无权限就强制跳转到指定页面。

    另外一种,是根据 后端返回的路由权限地址列表,使用addRoutes()动态的添加到对应的路由表中 。

  • 按钮层面,具体到页面内部后的操作访问能力,简单的就使用 v-if/show 进行显示隐藏控制即可,当然,也可以专门的做一个 v-permission 自定义指令,判断用户按钮级别权限,直接操作 DOM 是否显示。

56、说说你对 SSR 的理解?Vue 项目怎么进行 SEO 的优化?

  • SEO 是搜索引擎优化的体现,搜索引擎对网页进行识别,主要是对 h1、h2、title、img 、content 等内容进行识别,访问的多了,搜索引擎就记录最多的内容,具有优先推荐权。
  • Vue 打包出来的文件 都是 js 文件,js 文件需要运行在 浏览器中才能最终呈现内容,但是,搜索引擎不是浏览器,无法直接通过 JS 就获取到对应 HTML 标签信息,所以,无法进行 SEO 识别优化。
  • 这个时候,我就可以使用 Nuxt SSR 服务端渲染的解决方案,服务端渲染简单来说,就是 直接将 HTML 标签信息内容在 服务端就生产出来,浏览器运行的就不再是 单纯 的 js 文件,而是 实打实的 HTML 信息内容。