Vue面试题+详解答案(二)

226 阅读8分钟

16、v-model 原理

v-model 只是语法糖而已。
v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件。\

  • text 和 textarea 元素使用 value property 和 input 事件;
  • checkbox 和 radio 使用 checked property 和 change事件;
  • select 字段将 value 作为 prop 并将 change 作为事件。

注意:对于需要使用输入法的语言,你会发现 v-model 不会在输入法组合文字过程中得到更新。

在普通元素上:
input v-model='sth'
input v-bind:value='sth' v-on:input='sth = $event.target.value'

17、v-for为什么要加key

如果不使用key,Vue会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。key 是为Vue中Vnode的唯一标识,通过这个key,我们的diff操作可以更准确、更快速。
更准确: 因为带key就不是就地复用了,在sameNode函数 a.key === b.key 对比中可以避免就地复用的情况。所以更加准确。
更快速: 利用key的唯一性生成map对象来获取对应节点,比遍历方式块。

18、Vue事件绑定原理

原生事件绑定是通过 addEventListener 绑定给真实元素的,组件事件绑定是通过Vue自定义的on实现的。如果要在组件上使用原生事件,需要加.native修饰符,这样就相当于在父组件中把子组件当做普通的HTML标签,然后加上原生事件。 on实现的。如果要在组件上使用原生事件,需要加.native修饰符,这样就相当于在父组件中把子组件当做普通的HTML标签,然后加上原生事件。\ on、$emit 是基于发布订阅模式的,维护一个事件中心,on的时候将事件按名称存在事件中心里,称之为订阅者,然后emit将对应的事件进行发布,去执行事件中心里的对应的监听器。

19、vue-router 路由钩子函数是什么?执行顺序是什么?

路由钩子的执行流程,钩子函数种类有:全局守卫、路由守卫、组件守卫。

完整的导航解析流程:
1、导航被触发。
2、在失活的组件里调用 beforeRouterLeave 守卫。
3、调用全局的 beforeEach 守卫。
4、在重用的组件调用 beforeRouterUpdate 守卫(2.2+)。
5、在路由配置里面 beforeEnter。
6、解析异步路由组件。
7、在被激活的组件里调用 beforeRouterEnter。
8、调用全局的 beforeResolve 守卫(2.5+)。
9、导航被确认。
10、调用全局的 afterEach 钩子。
11、触发 DOM 更新。
12、调用 beforeRouterEnter 守卫中传给next的回调函数,创建好的组件实例会作为回调函数的参数传入。

20、vue-router 动态路由是什么?有什么问题。

我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,我们有一个 User组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染。那么,我们可以在 vue-router 的路由路径中使用“动态路径参数”(dynamic segment)来达到这个效果: const User = {
template: "

User

", };
const router = new VueRouter({
routes: [
// 动态路径参数 以冒号开头
{ path: "/user/:id", component: User },
],
});
问题:vue-router 组件复用导致路由参数失效怎么办?
解决方案:
1、通过watch监听路由参数再发请求
watch:{
"router":function(){
this.getData(this.router.params.xxx)\ }\ }\ 2、用 :key来阻止复用\ router-view :key="route.fullPath"

21、谈一下对 vuex 的个人理解

vuex 是专门为 vue 提供的全局状态管理系统,用于多个组件中数据共享、数据缓存等。(无法持久化、内部内心原理是通过创造一个全局实例 new Vue)

主要包括以下几个模块:

  • State:定义了应用状态的数据结构,可以在这里设置默认的初始化状态。
  • Getter:允许组件从Store中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性。
  • Mutation:是唯一更改 store 中状态的方法,且必须是同步函数。
  • Action:用于提交 mutation,而不是直接变更状态,可以包含任意异步请求。
  • Module:允许将单一的 Store 拆分更多个 store 且同时保存在单一的状态树中。

22、Vuex 页面刷新数据丢失怎么解决?

需要做 vuex 数据持久化,一般使用本地储存的方案来保存数据,可以自己设计存储方案,也可以使用第三方插件。
推荐使用 vuex-persist (脯肉赛斯特)插件,它是为 Vuex 持久化储存而生的一个插件。不需要你手动存取 storage,而是直接将状态保存至 cookie 或者 localStorage中。

23、Vuex 为什么要分模块并且加命名空间?

模块: 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能会变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块。

命名空间: 默认情况下,模块内部的 action、mutation、getter是注册在全局命名空间的 --- 这样使得多个模块能够对同一 mutation 或 action 做出响应。如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced:true 的方式使其成为带命名的模块。当模块被注册后,他所有 getter、action、及 mutation 都会自动根据模块注册的路径调整命名。

24、使用过 Vue SSR 吗?说说 SSR

SSR 也就是服务端渲染,也就是将 Vue 在客户端把标签渲染成 HTML 的工作放在服务端完成,然后再把 html 直接返回给客户端。

优点:
SSR 有着更好的 SEO、并且首屏加载速度更快。
缺点:
开发条件会受限制,服务器端渲染只支持 beforeCreate 和 created 两个钩子,当我们需要一些外部扩展库时需要特殊处理,服务端渲染应用程序也需要处于 Node.js 的运行环境。
服务器会有更大的负载需求。

25、vue 中使用了哪些设计模式?

1、工厂模式 - 传入参数即可创建实例
虚拟 DOM 根据参数的不同返回基础标签的 Vnode 和组件 Vnode。

2、单例模式 - 整个程序有且仅有一个实例
vuex 和 vue-router 的插件注册方法 install 判断如果系统存在实例就直接返回掉。

3、发布-订阅模式。(vue 事件机制)

4、观察者模式。(响应式数据原理)

5、装饰器模式(@装饰器的用法)

6、策略模式,策略模式指对象有某个行为,但是在不同的场景中,该行为有不同的实现方案 - 比如选项的合并策略。

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

这里只列举针对 Vue 的性能优化,整个项目的性能优化是一个大工程。

  • 对象层级不要过深,否则性能就会差。
  • 不需要响应式的数据不要放在 data 中(可以使用 Object.freeze() 冻结数据)
  • v-if 和 v-show 区分使用场景
  • computed 和 watch 区分场景使用
  • v-for 遍历必须加 key,key最好是id值,且避免同时使用 v-if
  • 大数据列表和表格性能优化 - 虚拟列表 / 虚拟表格
  • 防止内部泄露,组件销毁后把全局变量和时间销毁
  • 图片懒加载
  • 路由懒加载
  • 异步路由
  • 第三方插件的按需加载
  • 适当采用 keep-alive 缓存组件
  • 防抖、节流的运用
  • 服务端渲染 SSR or 预渲染

27、Vue.mixin 的使用场景和原理

在日常开发中,我们经常会遇到在不同组件中经常用到一些相同或者相似的代码,这些代码的功能相对独立,可以通过vue 的 mixin 功能抽离公共的业务逻辑,原理类似“对象的继承”,当组件初始化时会调用 mergeOptions 方法进行合并,采用策略模式针对不同的属性进行合并。当组件和混入对象含有相同名选项时,这些选项将以恰当的方式进行“合并”。

28、nextTick 使用场景和原理

nextTick 中的回调是在下次 DOM 更新循环结束之后执行的延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。主要思路就是采用微任务优先的方式调用异步方法去执行 nextTick 包装的方法。

29、keep-alive 使用场景和原理

keep-alive 是 Vue 内置的一个组件,可以实现组件缓存,当组件切换时不会对当前组件进行卸载。

  • 常用的两个属性 include/exclude,允许组件有条件的进行缓存。
  • 两个生命周期 activated/deactivated,用来得知当前组件是否处理活跃状态。
  • keep-alive 运用了 LRU 算法,选择最近最久未使用的组件予以淘汰。

扩展补充:LRU 算法是什么?

30、Vue.set 方法原理

了解 Vue 响应式原理的同学都知道在两种情况下修改 Vue 是不会触发视图更新的。
1、在实例创建之后添加新的属性到实例上(给响应式对象新增属性)
2、直接更改数组下标来修改数组的值。\

Vue.set 或者说是 $set 原理如下

因为响应式数据 我们给对象和数组本身新增了__ob__属性,代表的是 Observer 实例。当给对象新增不存在的属性,首先会把新的属性进行响应式跟踪 然后会触发对象 ob 的dep收集到的 watcher 去更新,当修改数组索引时我们调用数组本身的 splice 方法去更新数组。

转自 https://www.cnblogs.com/wenshaochang123/p/14888494.html (16-30)