面试|Vue

150 阅读7分钟

一、原生JS和框架的区别

1.1 代码层面

原生JS框架
缺少规划,代码混乱结构化开发
缺少限制,容易冲突独立文件,独立作用域
缺少支撑,能力要求高提供支持,只关心业务
  1. 原生JS的代码比较随意,没有规范性,框架对每个页面的代码布局做了规范,有利于可维护性。
  2. 原生JS开发不是多人并行开发的,若修改代码很容易造成全局变量和其他业务发生变化,而框架使用webpack等打包工具,实现了各页面的独立开发,相互不影响,有自己独立的作用域,和其他页面不会产生冲突,解决了多人并发开发的问题。
  3. 原生JS所有的架构,使用工具都需要手动编写,框架将大部分工具封装好了,直接用。

1.2 效率问题

原生JS框架
关注所有流程只关注业务
团队效率低并行开发
测试效率低模块测试,自动化测试
  1. 原生JS开发者需要关注所有流程,还不能并行开发,效率很低,框架使得开发者仅仅只需要关注业务逻辑的实现,不需要关注其他,提高了效率
  2. JS的影响是全局的,团队开发效率太低,框架的修改只会影响自己的模块,不会影响他人,可以多人开发。

二、Vue的生命周期

Vue的生命周期主要有:

  • 创建 —— 在组件创建之前执行
  • 挂载 —— DOM被挂载时执行
  • 更新 —— 当响应数据被修改时执行
  • 销毁 —— 在元素被销毁之前立即执行

并且每个生命周期被分为了两个钩子。

Vue2Vue3
beforeCreatesetup()
createdsetup()
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeDestroyonBeforeUnmount
destroyedonUnmounted
errorCapturedonErrorCaptured

三、Vue的双向绑定原理

1.作用在表单上时,动态绑定了input的value指向了searchText,并在触发了input事件的时候动态把searchText设置为目标值:

<input v-model="searchText">
//可以等价为以下方式
<input
  :value="searchText"
  @input="searchText = $event.target.value"
/>

  1. 作用在组件上,v-modek默认会利用名为value的prop和名为input的事件,本质是一个父子组件通信语法糖,通过prop和$emit实现。
<CustomInput v-model="searchText" />
//展开如下:
<CustomInput
  :modelValue="searchText"
  @update:modelValue="newValue => searchText = newValue"
/>
//组件内部如下:
<!-- CustomInput.vue -->
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>

<template>
  <input
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
  />
</template>

四、组件之间通信方式

4.1 props/$emit(父子通信)

父组件通过props进行定义一个参数传给下一个子组件,子组件用$emit绑定一个自定义事件,当这个事件被执行的时候就会将参数传递给父组件,而父组件通过v-on监听并接收参数。

4.2 provide/inject(父子,祖孙)

该方法可以用于父子、祖孙组件之间的通信。

  • provide 钩子用来发送数据或方法
  • inject钩子用来接收数据或方法

4.3 eventBus事件总线、Vuex(任意组件通信)

该方法是Vue2独有的方法,Vue3移除。

  • 使用 eventBus ,其实就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。

  • $emit 向其他组件传递参数

  • $on 接收其他组件传递参数

也可以使用Vuex进行全局管理。

五、响应式原理

Vue2---Object.defineProperty

Vue2在实例初始化时遍历data中的所有属性,并使用Object.defineProperty把这些属性全部转为getter/setter。并劫持各个属性getter和setter,在数据变化时发布给消息订阅者,触发相应的监听回调。 有以下缺点:

  • 初始化时需要遍历对象所有 key,如果对象层次较深,性能不好

  • 通知更新过程需要维护大量 dep 实例和 watcher 实例,额外占用内存较多

  • Object.defineProperty 无法监听到数组元素的变化,只能通过劫持重写数方法

  • 动态新增,删除对象属性无法拦截,只能用特定 set/delete API 代替

  • 不支持 Map、Set 等数据结构

Vue3---Proxy

Vue3使用Proxy来监控数据变化。Proxy是ES6中提供的功能,其作用为:定义基本操作的自定义行为。其有以下特点:

  • Proxy 直接代理整个对象而非对象属性,这样只需做一层代理就可以监听同级结构下的所有属性变化,包括新增属性和删除属性。

  • 它的处理方式是在 getter 中去递归响应式,这样的好处是真正访问到的内部属性才会变成响应式,简单的可以说是按需实现响应式,减少性能消耗。

  • Proxy 可以监听数组的变化。

六、计算属性computed和Watch属性

6.1 computed

  • 它支持缓存,只有当依赖的数据发生了变化,才会重新计算
  • 不支持异步,当Computed中有异步操作时,无法监听数据的变化
  • computed的值仅会在其响应式依赖更新时才重新开始计算
  • computed属性一般为只读的,其内部有get和set算法,默认使用get方法,当数据变化时使用set

6.2 watch

  • 不支持缓存,数据变化时,它就会触发相应操作

  • 支持异步监听

  • 监听的函数接收两个参数,第一个参数是最新的值,第二个是变化之前的值,当一个属性发生变化时,就需要执行相应的操作。

  • 监听数据必须是data中声明的或者从父组件传递过来的数据,当发生变化时,函数有两个参数:

    • immediate:组件加载立即触发回调函数
    • deep:深度监听,发现数据内部的变化,在复杂数据类型中使用,例如数组中的对象发生变化。需要注意的是,deep无法监听到数组和对象内部的变化。

七、Vue2和Vue3的区别

7.1 监听机制的改变

Vue3使用的是Proxy对数据进行代理,消除了Vue2Object.defineProperty的很多限制,Vue3可以监听到对象属性的添加和删除,可以监听数组的变化,还有Map、Set、WeakMap、WeakSet。

7.2 API模式不同

Vue2采用的是选项式API,Vue3采用组合式API。Vue3可以更好的组织和重用逻辑代码,更利于维护。

7.3 生命周期勾子不同

具体情况见上。

7.4 Typescript支持

Vue3 对 TypeScript 的支持更加完善,可以提供更好的类型检查和错误提示。

总之,Vue3 在性能、代码组织、类型检查和数据响应式等方面都有所改进和优化,可以提供更好的开发体验和性能。

八、Vue-Router

8.1 hash模式和history模式

Hash路由

Hash路由是指路由信息存放在URL的hash部分,即#后面的内容。在使用hash路由时,浏览器的URL不会向服务器发起请求,只是对URL进行了修改,因此不会刷新页面。通过监听hashchange事件,可以在hash改变时更新页面内容。

Hash路由的特点:

  • hash改变不会导致页面刷新,用户体验较好。
  • hash不会被包含在HTTP请求中,对后端不会产生影响。
  • 支持浏览器前进、后退操作。

History路由

History路由是指路由信息存放在URL的路径部分。在使用history路由时,URL发生变化会向服务器发起请求,服务器需要返回对应的页面内容。通过history API可以实现前进、后退等功能。

History路由的特点:

  • 可以使用HTTP请求来获取页面内容,但每次URL发生变化时都会向服务器发起请求,会影响性能。
  • 支持浏览器前进、后退操作。

综合来说,hash路由适合实现单页面应用(SPA),而history路由适合多页面应用。

为什么history模式会有404问题?

在使用history模式时,由于服务器端没有相应的路由配置,当用户在地址栏输入一个路由地址时,服务器无法匹配到对应的资源,因此会返回404。因此,需要在服务器端进行配置,将所有的路由都指向一个入口文件,然后在该入口文件中通过路由管理器根据不同的 URL 显示相应的内容。

为什么hash模式没有404问题?

在使用 hash 模式时,URL 中的 hash(即 # 后面的部分)被当做是客户端的内部资源,不会被发送到服务器端。因此,无论用户在地址栏输入什么样的 hash 路径,服务器都不会返回 404 错误,因为服务器根本不会对 hash 路径进行处理。

相对于 history 模式而言,hash 模式的优点是可以避免在服务器端配置通配符路由。但是,由于 hash 的存在,每次路由切换时都会在 URL 中添加新的 hash,可能会让 URL 看起来比较混乱。同时,在 SEO 优化方面也会有一些问题,因为搜索引擎不会将 hash 作为独立的 URL 处理,导致无法将 hash 路径索引到搜索结果中。