Vue求职无忧含答案
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 信息内容。