2024高频前端面试题 Vue2 和 Vue3 篇

HTML和CSS篇:2024高频前端面试题 HTML 和 CSS 篇-CSDN博客

JavaScript 和 ES6 篇: 2024高频前端面试题 JavaScript 和 ES6 篇-CSDN博客

* Vue2 和 Vue3的区别:

1)双向数据绑定原理的区别

2)根节点的不同

Vue2只能一个根节点

Vue3在组件中可以放置多个根节点

3)Vue3中采用composition API 

vue2:采用的选项型API(opsition API)
vue3:采用的组合型API(composition API)

4)建立的数据方式不同 

vue2:数据是放置在data属性中
vue3:需要使用setup 方法,该方法在初始化构造的时候触发
注:ref:需要value 访问,内部还是使用的defineProperty set get 方法进行监听(proxy 不支持基本类型的监听)
reactive: 使用的proxy对数据进行的一个代理

5)生命周期函数不同 

6)diff算法不同

7)父子传参不同

vue2:父传子,用props,子传父用事件 Emitting Events。在vue2中,会调用this$emit然后传入事件名和对象。

vue3:父传子,用props,子传父用事件 Emitting Events。在vue3中的setup()中的第二个参数content对象中就有emit,那么我们只要在setup()接收第二个参数中使用分解对象法取出emit就可以在setup方法中随意使用了。

1. 什么是MVVM?

M - Model 数据:负责数据管理和业务逻辑。
V - View 视图:负责用户界面的展示和呈现。
VM - ViewModel 视图-数据:它是View和Model的粘合体,负责View和Model的交互和协作

vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的, 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变; 

核心:关于VUE双向数据绑定,其核心是 Object.defineProperty()方法,get set 方法。

在MVVM的框架下视图和模型是不能直接通信的。它们通过ViewModel来通信,ViewModel通常要实现一个observer观察者,当数据发生变化,ViewModel能够监听到数据的这种变化,然后通知到对应的视图做自动更新,而当用户操作视图,ViewModel也能监听到视图的变化,然后通知数据做改动,这实际上就实现了数据的双向绑定。并且MVVM中的View 和 ViewModel可以互相通信。

MVVM 是一种软件架构模式。它是基于 MVC 的一种演变,将视图和数据绑定的方式更加紧密地结合在一起。 

2. 什么是MVC? 

M - Model 数据:负责数据管理和业务逻辑。模型表示应用程序中的数据结构以及对数据的操作。
V - View 视图负责用户界面的展示和呈现,通常是用户可以看到和与之交互的部分。
C - Controller 控制器: 负责接收用户的输入并作出响应,它处理用户与模型和视图之间的交互。控制器将用户的操作转发给模型进行处理,并将模型的结果传递给视图进行展示。

MVC 的优势:
能够将应用程序的各个功能模块分离开来,提高代码的可维护性和可扩展性。通过明确定义了各个组件的职责,开发人员可以更好地组织和管理代码,同时也使得代码更容易被复用。

3. MVVM 和 MVC的区别 

1、mvvm各部分的通信是双向的,而mvc各部分通信是单向的;

2、mvvm是真正将页面与数据逻辑分离放到js里去实现,而mvc里面未分离

MVC允许在不改变视图的情况下改变视图对用户输入的响应方式,用户对View的操作交给了Controller处理,在Controller中响应View的事件调用Model的接口对数据进行操作,一旦Model发生变化便通知相关视图进行更新。 

4. Vue2响应式原理 

对象类型:

使用 Object.defineProperty 遍历对象的每一个属性,把每一个属性变成一个 getter 和 setter 函数,读取属性的时候调用 getter,给属性赋值的时候就会调用 setter,这就是数据劫持。

数组类型:

通过重写更新数组的一系列方法,保留原功能的基础上增加一些数据劫持的代码(也就是将数据变为可监控的)来实现拦截。

7个方法:push、pop、shift、unshift、splice、sort、reverse。

存在问题:

1.新增属性、删除属性, 界面不会更新。

2.直接通过下标修改数组, 界面不会自动更新。

解决方法:

vue2中 $set 可以解决这些问题。

5.  Vue3响应式原理 

通过(Proxy)代理实现: 拦截对象中任意属性的变化, 包括属性值的读写, 属性的添加, 属性的删除等操作。

通过(Reflect)(反射); 被代理的对象, 属性进行操作。

vue3.0 中不存在vue2.0 中说的这些问题

在一个对象中新增, 删除, 修改属性, 界面不会自动更新。

直接通过下标修改数组, 界面不会自动更新。

6. Proxy 与 Object.defineProperty 优劣对比 

1)Proxy的优势如下:

  1. Proxy可以直接监听对象⽽⾮属性 。
  2. Proxy可以直接监听数组的变化 。
  3. Proxy有多达13种拦截⽅法,不限于apply、ownKeys、deleteProperty、has等等是 Object.defineProperty 不具备的 。
  4. Proxy返回的是⼀个新对象,我们可以只操作新的对象达到⽬的,⽽ Object.defineProperty 只能遍历对象属性直接修改。
  5. Proxy作为新标准将受到浏览器⼚商重点持续的性能优化,也就是传说中的新标准的性能红利 。

2)Object.defineProperty的优势如下:

  1. 兼容性好,⽀持IE9。

7. Vue2和Vue3的diff的区别 

diff 算法有以下过程:
  • 同级比较,再比较子节点
  • 先判断一方有子节点一方没有子节点的情况(如果新的 children 没有子节点,将旧的子节点移除)
  • 比较都有子节点的情况(核心 diff)
  • 递归比较子节点
Vue2:

Vue2 的核心 Diff 算法采用了双端比较的算法,同时从新旧 children 的两端开始进行比较,借助 key 值找到可复用的节点,再进行相关操作。相比 React 的 Diff 算法,同样情况下可以减少移动节点次数,减少不必要的性能损耗,更加的优雅。

Vue3:

Vue3.x 借鉴了 ivi 算法和 inferno 算法

在创建 VNode 时就确定其类型,以及在 mount/patch 的过程中采用位运算来判断一个 VNode 的类型,在这个基础之上再配合核心的 Diff 算法,使得性能上较 Vue2.x 有了提升。该算法中还运用了动态规划的思想求解最长递归子序列。

详细内容比较多,但这个是重点部分。请跳转至:

Vue2 和 Vue3 的 Diff 算法的区别-CSDN博客

Vue diff算法_vue2 diff算法和vue3diff算法-CSDN博客

8. 虚拟 DOM 的优缺点 

优点:
  • 性能优化:虚拟DOM通过减少不必要的DOM操作,提高渲染性能。它使用一个高效的diff算法来计算出真正需要更新的节点,最大限度地减少DOM操作,从而提高性能。
  • 抽象化DOM操作:由于虚拟DOM以JavaScript对象为基础,不依赖真实平台环境,因此可以跨平台操作,例如在浏览器平台、Weex、Node等环境中使用。
  • 无需手动操作DOM:Vue的虚拟DOM可以自动处理视图更新,开发者只需要关注数据变化,无需手动操作DOM,大大提高了开发效率。
缺点: 
  • 首次渲染大量DOM时性能较差:由于虚拟DOM需要进行计算和比较,所以在首次渲染大量DOM时,可能会比直接操作DOM慢。
  • 不适合小型项目:对于小型项目或简单页面,使用虚拟DOM可能会增加额外的计算开销,此时直接操作DOM可能更为简单高效。

9. 生命周期的理解

Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模版、挂载 Dom -> 渲染、更新 -> 渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。

10. Vue2的生命周期

创建阶段:

beforeCreate:在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
created:在实例创建完成后被调用,此阶段完成了数据观测 (data observer)、属性和方法的运算,以及 watch/event 事件的设置。但是此时还没有挂载到 DOM 上。

挂载阶段:

beforeMount:在挂载开始之前被调用,相关的 render 函数首次被调用。

mounted:在实例被挂载到 DOM 后调用,此阶段完成了模板编译并且将实例挂载到 DOM 上。

更新阶段:

beforeUpdate:在数据更新之前被调用,发生在虚拟 DOM 重新渲染和打补丁之前。

updated:在数据更新完成后被调用,实例的 DOM 已经更新。

销毁阶段:

beforeDestroy:在实例销毁之前调用,此时实例仍然完全可用。

destroyed:在实例销毁后调用,此阶段完成了实例的事件监听器和子组件的销毁。

两个特殊的生命周期钩子函数: 

activated:在使用 keep-alive 组件时,被激活的组件会调用该函数。

deactivated:在使用 keep-alive 组件时,被停用的组件会调用该函数。

11. Vue3的生命周期         

1)普通写法:      2)setup中写生命周期:
beforeCreatesetup()
createdsetup()
beforeMount onBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updated onUpdated
beforeUnmount onBeforeUnmount
unmounted onUnmounted

12. Vue2和Vue3生命周期区别

13. 父组件和子组件生命周期钩子函数执行顺序 

执行顺序:

父组件先创建,然后子组件创建;子组件先挂载,然后父组件挂载。

父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
销毁过程:
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

14. 在哪个生命周期内调用异步请求?

可以在钩子函数 createdbeforeMountmounted 中进行调用,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。

但是本人推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:

  • 能更快获取到服务端数据,减少页面 loading 时间;
  • ssr 不支持 beforeMount 、mounted 钩子函数,所以放在 created 中有助于一致性;

15. 父组件可以监听到子组件的生命周期吗? 

比如有父组件 Parent 和子组件 Child,如果父组件监听到子组件挂载 mounted 就做一些逻辑处理,可以通过以下写法实现:

// Parent.vue
<Child @mounted="doSomething"/>
    
// Child.vue
mounted() {
  this.$emit("mounted");
}

以上需要手动通过 $emit 触发父组件的事件,更简单的方式可以在父组件引用子组件时通过 @hook 来监听即可,如下所示

//  Parent.vue
<Child @hook:mounted="doSomething" ></Child>

doSomething() {
   console.log('父组件监听到 mounted 钩子函数 ...');
},
    
//  Child.vue
mounted(){
   console.log('子组件触发 mounted 钩子函数 ...');
},    
    
// 以上输出顺序为:
// 子组件触发 mounted 钩子函数 ...
// 父组件监听到 mounted 钩子函数 ... 

当然 @hook 方法不仅仅是可以监听 mounted,其它的生命周期事件,例如:created,updated 等都可以监听。

16. keep-alive 

在组件切换过程中将状态保留在内存中,防止重复渲染DOM,提高页面加载性能与用户体验

可以设置以下props属性(参数):

  1. include:匹配的路由/组件会被缓存
  2. exclude:匹配的路由/组件不会被缓存
  3. max:最大缓存数

当时用keep-alive,只会创建一次,即时切出该组件,也不会销毁该组件,再进入该组件,也不会创建。

当引入keep-alive 的时候,页面第一次进入,钩子的触发顺序 created => mounted => activated

退出时触发deactivated。当再次进入或退出时,只触发activated和deactivated。钩子的触发顺序(destroyed => activated

17. 组件中 data 为什么是一个函数? 

因为 Vue 在创建组件实例时,会为每个组件实例都创建一个独立的数据作用域

如果将 data 直接定义为一个对象,那么所有组件实例都将共享同一个数据对象,这样就无法实现数据的隔离。

data 是函数的话那么每次创建组件实例时,都会调用这个函数并返回一个新的对象

18. vue中key的作用 

key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】, 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较。

作用:

是为了更高效的更新虚拟DOM,它的作用是标识虚拟DOM的唯一性,当虚拟DOM发生变化时,vue会根据key的变化来判断是否需要更新虚拟DOM。通过key的作用,可以更高效地更新虚拟DOM,提高了页面的性能和用户体验

19. computed 和 watch 的区别和运用的场景? 

computed:计算属性,依赖于其他属性,并且computed的值有缓存。只有它依赖的属性值(响应式依赖)发生变化,下一次获取computed的值时才会重新计算computed的值。

watch:更多的是【观察】的作用,类似于某些数据的监听回调,每当监听的数据发生变化时,都会执行回调进行后续操作。

运用场景:

  • computed:当我们要进行数值计算,并且依赖于其他数据时,这时应该使用computed,因为利用computed的缓存特性,可以避免每次获取值时都重复计算。
  • watch: 当我们在数据发生变化时执行异步或开销较大的操作时,应该使用watch,使用watch选项允许我们执行一步操作(访问一个API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些是computed(计算属性)无法实现的

20. watch 和 watchEffect 的区别?

watch 和 watchEffect 都能响应式地执行有副作用的回调。它们之间的主要区别是追踪响应式依赖的方式

  • watch 只追踪明确侦听的数据源。它不会追踪任何在回调中访问到的东西。另外,仅在数据源确实改变时才会触发回调。watch 会避免在发生副作用时追踪依赖,因此,我们能更加精确地控制回调函数的触发时机。 
  • watchEffect,则会在副作用发生期间追踪依赖。它会在同步执行过程中,自动追踪所有能访问到的响应式属性。这更方便,而且代码往往更简洁,但有时其响应性依赖关系会不那么明确
执行时机不同:

watch 是惰性地执行副作用,他不会立即执行,但可以配置immediate,使其主动触发 。

watchEffect 是立即执行的,在页面加载时会主动执行一次,来收集依赖。

参数不同:

watch 至少要有两个参数,第一个是监听的数据,第二个是回调函数,第三个是配置项。

watchEffect 只需要一个回调函数,不需要传递侦听的数据,它会在页面加载时主动执行一次,来收集依赖。

结果不同:

watch 可以获取新值和旧值

watchEffect 获取不到更改前的值

watchEffect的解释:

1、立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数
2、如果你需要侦听一个嵌套数据结构中的几个属性,watchEffect() 可能会比深度侦听器更有效,因为它将只跟踪回调中被使用到的属性,而不是递归地跟踪所有的属性。 

21. 组件间通信有哪几种方式? 

1)props / $emit

父组件通过 props 向子组件传递数据,子组件通过 $emit 和父组件通信

2)ref / $refs

子组件绑定ref父组件通过 $refs. 读取子组件的属性和方法

3)eventBus事件总线($emit / $on)
4)依赖注入(provide / inject)

子组件 inject , 父组件 provide

pc:依赖注入所提供的属性是非响应式的

5) $parent / $children

$parent 访问到的是上一级父组件的实例

$children 的值是数组,而 $parent是个对象

6)$attrs / $listeners
7)Vuex 和 Pinia
总结:
父子组件间通信

1)props,emit

2) ref,$refs 

3)provide,inject

跨代组件间通信

1)$attrs,$listeners

兄弟组件间通信

1) $parent + $refs

任意组件间通信

1)eventBus事件总线

2)Vuex 和 Pinia

详解:

vue中组件间通信的6种方式_跨组件通信vue-CSDN博客

22. v-if 和 v-for 的优先级哪个高? 

vue2 中 v-for 的优先级更高。(2o)

vue3 中优先级改变了,v-if 的优先级更高。 (3i)

同一个标签中同时使用了 v-for 和 v-if:

由于v-for的优先级比v-if高,所以每循环一次就会去v-if一次,而v-if是通过创建和销毁dom元素来控制元素的显示与隐藏,所以就会不停的去创建和销毁元素,造成页面卡顿,性能下降。

解决办法:

1)用计算属性去过滤v-for使用的数组

2)添加 <template> 让 v-for 和 v-if,不在同一标签上

23. v-show 与 v-if 有什么区别? 

v-if :

真正的条件渲染,动态的向DOM树内添加或者删除DOM元素

也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

v-show :

就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 的 “display” 属性进行切换。

总结:

所以,v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show 则适用于需要非常频繁切换条件的场景。

24. delete 和 Vue.delete 删除数组的区别是什么? 

delete:

 只是被删除的元素变成了 empty/undefined 其他的元素的键值还是不变。 

Vue.delete :

是直接将元素从数组中完全删除改变了数组其他元素的键值

24. 全局注册和局部注册自定义指令 

局部注册:

<script setup>
// 在模板中启用 v-focus
const vFocus = {
  mounted: (el) => el.focus()
}
</script>

<template>
  <input v-focus />
</template>

全局注册:

const app = createApp({})

// 使 v-focus 在所有组件中都可用
app.directive('focus', {
  /* ... */
})

指令钩子:

const focus= {
  // 在绑定元素的 attribute 前
  // 或事件监听器应用前调用
  created(el, binding, vnode, prevVnode) {
    // 下面会介绍各个参数的细节
  },
  // 在元素被插入到 DOM 前调用
  beforeMount(el, binding, vnode, prevVnode) {},
  // 在绑定元素的父组件
  // 及他自己的所有子节点都挂载完成后调用
  mounted(el, binding, vnode, prevVnode) {},
  // 绑定元素的父组件更新前调用
  beforeUpdate(el, binding, vnode, prevVnode) {},
  // 在绑定元素的父组件
  // 及他自己的所有子节点都更新后调用
  updated(el, binding, vnode, prevVnode) {},
  // 绑定元素的父组件卸载前调用
  beforeUnmount(el, binding, vnode, prevVnode) {},
  // 绑定元素的父组件卸载后调用
  unmounted(el, binding, vnode, prevVnode) {}
}

25. v-model 的原理 

v-model本质上是一个语法糖

v-model其实就是 :value@input事件的简写。

26. reactive 和 ref 对比区别 

定于数据角度对比:
ref 用来定义:基本类型数据
reactive 用来定义:对象、或数组类型的数据
备注:ref也可以用来定义对象或数组类型数据,它内部会自动通过 reactive 转为代理对象

原理角度对比:
ref 通过 Object.defineProperty() 的 get 与 set 来实现响应式的(数据劫持)
reactive 通过使用 Proxy 来实现响应式(数据劫持),并通过Reflect 操作源对象内部的数据。 

使用角度对比:
ref 定义的数据:操作数据需要 .value,读取数据时模版中直接读取不需要 .value
reactive 定义的数据:操作数据与读取数据,均不需要 .value 

27. toRef() 和 toRefs() 

toRef():

可以将值、refs 或 getters 规范化为 refs (3.3+)。

也可以基于响应式对象上的一个属性,创建一个对应的 ref。这样创建的 ref 与其源属性保持同步改变源属性的值将更新 ref 的值,反之亦然。

toRefs():

将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向源对象相应属性的 ref。每个单独的 ref 都是使用 toRef() 创建的。

当从组合式函数中返回响应式对象时,toRefs 相当有用。使用它,消费者组件可以解构/展开返回的对象而不会失去响应性。

toRefs 在调用时只会为源对象上可以枚举的属性创建 ref。如果要为可能还不存在的属性创建 ref,请改用 toRef

28. NextTick()作用

vue 更新 DOM 是异步更新的,数据变化,DOM 的更新不会马上完成,nextTick 的回调是在下次 DOM 更新循环结束之后执行的延迟回调

29. scoped作用与原理 

作用:组件css作用域,避免子组件内部的css样式被父组件覆盖

原理:给元素添加一个自定义属性 v-data-xxxxx, 通过属性选择题来提高css权重值。

30. 路由守卫作用/对比axios拦截器 

相同点:
  • 都是钩子函数(回调函数的一种,到某个时机了自动触发)
  • 都是起到拦截作用
不同点: 
  • 功能不同 :axios拦截器拦截网络请求, 导航守卫拦截路由跳转
  • 应用场景不同 :
  1. axios拦截器一般用于发送token
  2. 导航守卫用于页面跳转权限管理(有的页面可以无条件跳转,例如登录注册页可以无条件跳转。有的页面需要满足条件才能跳转,例如购物车页面就需要用户登录才可以跳转)

31. 服务端渲染 SSR 的优缺点

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

优点:
  • 更好的 SEO: 因为 SPA 页面的内容是通过 Ajax 获取,而搜索引擎爬取工具并不会等待 Ajax 异步完成后再抓取页面内容,所以在 SPA 中是抓取不到页面通过 Ajax 获取到的内容;而 SSR 是直接由服务端返回已经渲染好的页面(数据已经包含在页面中),所以搜索引擎爬取工具可以抓取渲染好的页面;
  • 更快的内容到达时间(首屏加载更快): SPA 会等待所有 Vue 编译后的 js 文件都下载完成后,才开始进行页面的渲染,文件下载等需要一定的时间等,所以首屏渲染需要一定的时间;SSR 直接由服务端渲染好页面直接返回显示,无需等待下载 js 文件及再去渲染等,所以 SSR 有更快的内容到达时间;
缺点:
  • 更多的开发条件限制: 例如服务端渲染只支持 beforCreate 和 created 两个钩子函数,这会导致一些外部扩展库需要特殊处理,才能在服务端渲染应用程序中运行;并且与可以部署在任何静态文件服务器上的完全静态单页面应用程序 SPA 不同,服务端渲染应用程序,需要处于 Node.js server 运行环境;
  • 更多的服务器负载:在 Node.js 中渲染完整的应用程序,显然会比仅仅提供静态文件的 server 更加大量占用CPU 资源 (CPU-intensive - CPU 密集),因此如果你预料在高流量环境 ( high traffic ) 下使用,请准备相应的服务器负载,并明智地采用缓存策略。

32. vue3有哪些新的组件? 

<Teleport> 是一个内置组件,它可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去。

<Suspense> 是一个内置组件,用来在组件树中协调对异步依赖的处理。它让我们可以在组件树上层等待下层的多个嵌套异步依赖项解析完成,并可以在等待时渲染一个加载状态。(等待异步组件时渲染一些额外内容

*性能优化

1. vue 如何快速定位那个组件出现性能问题的 

timeline ⼯具。 通过 timeline 来查看每个函数的调⽤时常,定位出哪个函数的问题,从⽽能判断哪个组件出了问题。

2. Vue 项目进行哪些优化 

代码层面的优化:
  • v-if 和 v-show 区分使用场景
  • computed 和 watch 区分使用场景
  • v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
  • 长列表性能优化
  • 事件的销毁
  • 图片资源懒加载
  • 路由懒加载
  • 第三方插件的按需引入
  • 优化无限列表性能
  • 服务端渲染 SSR or 预渲染
SEO 优化 :
  • 预渲染
  • 服务端渲染 SSR
用户体验: 
  • 骨架屏
  • PWA
Webpack 层面的优化:
  • Webpack 对图片进行压缩
  • 减少 ES6 转为 ES5 的冗余代码
  • 提取公共代码
  • 模板预编译
  • 提取组件的 CSS
  • 优化 SourceMap
  • 构建结果输出分析
  • Vue 项目的编译优化
基础的 Web 技术的优化:
  • 开启 gzip 压缩
  • 浏览器缓存
  • CDN 的使用
  • 使用 Chrome Performance 查找性能瓶颈

3. vue 中的 spa 应用如何优化首屏加载速度?

  • 请求优化:CDN 将第三方的类库放到 CDN 上,能够大幅度减少生产环境中的项目体积,另外 CDN 能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。
  • 缓存:将长时间不会改变的第三方类库或者静态资源设置为强缓存,将 max-age 设置为一个非常长的时间,再将访问路径加上哈希达到哈希值变了以后保证获取到最新资源,好的缓存策略有助于减轻服务器的压力,并且显著的提升用户的体验
  • gzip开启 gzip 压缩,通常开启 gzip 压缩能够有效的缩小传输资源的大小。
  • http2:如果系统首屏同一时间需要加载的静态资源非常多,但是浏览器对同域名的 tcp 连接数量是有限制的(chrome 为 6 个)超过规定数量的 tcp 连接,则必须要等到之前的请求收到响应后才能继续发送,而 http2 则可以在多个 tcp 连接中并发多个请求没有限制,在一些网络较差的环境开启 http2 性能提升尤为明显。

  • 懒加载:当 url 匹配到相应的路径时,通过 import 动态加载页面组件,这样首屏的代码量会大幅减少,webpack 会把动态加载的页面组件分离成单独的一个 chunk.js 文件
  • 预渲染:由于浏览器在渲染出页面之前,需要先加载和解析相应的 html、css 和 js 文件,为此会有一段白屏的时间,可以添加loading,或者骨架屏幕尽可能的减少白屏对用户的影响体积优化
  • 合理使用第三方库:对于一些第三方 ui 框架、类库,尽量使用按需加载,减少打包体积
  • 使用可视化工具分析打包后的模块体积webpack-bundle- analyzer 这个插件在每次打包后能够更加直观的分析打包后模块的体积,再对其中比较大的模块进行优化
  • 提高代码使用率利用代码分割,将脚本中无需立即调用的代码在代码构建时转变为异步加载的过程
  • 封装:构建良好的项目架构,按照项目需求就行全局组件,插件,过滤器,指令,utils 等做一 些公共封装,可以有效减少我们的代码量,而且更容易维护资源优化
  • 图片懒加载:使用图片懒加载可以优化同一时间减少 http 请求开销,避免显示图片导致的画面抖动,提高用户体验
  • 使用 svg 图标:相对于用一张图片来表示图标,svg 拥有更好的图片质量,体积更小,并且不需要开启额外的 http 请求

**构建工具:Webpack 和 Vite 的区别 

1. 底层的语言

  • webpack是基于nodejs构建JavaScript 是以毫秒计数。
  • vite是基于esbulid预构建依赖,esbulid是采用go语言编写的,go语言纳秒级别的。

2. 打包过程

  • webpack:分析各个模块之间的依赖=>然后进行编译打=>打包后的代码在本地服务器渲染。随着模块增多,打包的体积变大,造成热更新速度变慢。
  • vite:启动服务器=>请求模块时按需动态编译显示。
vite:
  • 开发环境:基于 原生 ES 模块(Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际使用时才会被处理。)
  • 生产环境:使用 Rollup 打包

3. 配置方式

  • webpack配置复杂,需要配置各种loaderplugin

  • Vite配置简单,基于 Rollup,大多数功能开箱即用

4. TypeScript支持

  • webpack需要额外的loader处理TypeScript

  • Vite内置了对TypeScript的支持

5. 生态系统

  • webpack的生态更加丰富成熟
  • Vite作为较新方案,生态还在快速发展中

6. 总结

Vite具有更快的启动速度、轻量的配置、更好的HMR和SSR支持等特点,适合现代化的框架。但它也存在部分生态缺失的问题。Webpack具有更全面的生态和插件支持,但配置复杂,构建速度较慢。不同场景下可根据需求选择不同的工具。

1. webpack常用开发是提高效率的插件 

//path模块是node.js中处理路径的核心模块。可以方便的处理关于文件路径的问题。
//path路径参数   
const path = require('path')

//解析和转换.vue文件,提取出其中的逻辑代码script,样式代码style以及HTML模板template,
再分别将它们交给对应的loader去处理。
//使用vue-loader@15以上都需要使用vueloaderplugin这个插件
const VueLoaderPlugin = require('vue-loader/lib/plugin');

//html-webpack-plugin插件 生成的内存中的页面已帮我们创建并正确引用了打包编译生成的js及css文件
const htmlWebpackPlugin = require('html-webpack-plugin');

//mini-css-extract-plugin 插件是 webpack4+ 版本的,可以直接安装使用。
这里只能把所有样式包括css、less都打包到一个css文件,然后再 link 进页面。
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

//性能分析页面工具
const BundleAnalyzerPlugins = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;

**网络安全 

1. XSS攻击及防范

XSS称为 跨站脚本攻击

  1. 攻击者在目标网站上注入恶意代码,当用户浏览目标网站时,浏览器会渲染整个HTML文档,这个过程中出现了不被预期的脚本指令,并且被浏览器执行了XSS就会发生
  2. 利用这些恶意代码,攻击者可以获取用户的敏感信息如 CookiesessionId 等,控制用户的账号权限,进而危害数据安全
防范: 
  1. 转义HTML
  2. 关注高危API
  3. Content Security Policy(内容安全策略,简称csp
  • 用于检测并阻止网页加载非法资源的安全策略,可以减轻xss攻击带来的危害和数据注入等攻击。
  1. 开启http only

禁止JavaScript读取某些敏感Cookie,攻击者完成XSS注入后也无法窃取此Cookie

2. 什么是CSRF攻击如何防范 

CSRF攻击指的是跨站请求伪造。

攻击者诱导用户进入第三方网站,然后该网站向被攻击网站发送跨域请求。

如果用户在被攻击的网站中保存了登录状态,那么攻击者就会利用这个登录状态绕过后台的用户验证,冒充用户向服务器执行一些操作

本质:

利用了Cookie会在同源请求中携带发送给服务器的特点,以此来实现用户的冒充

防范:
  • 同源检测
  • Token
  • 双重Cookie验证
  • 在设置Cookie属性的时候设置Samesite 

**Http常见的状态码 

1xx(临时响应)

表示临时响应并需要请求者继续执行操作的状态代码。

  • 100继续) 请求者应当继续提出请求。 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。
  • 101切换协议) 请求者已要求服务器切换协议,服务器已确认并准备切换。

2xx (成功)

表示成功处理了请求的状态代码。 

  • 200 成功) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。
  • 201 已创建) 请求成功并且服务器创建了新的资源。
  • 202 已接受) 服务器已接受请求,但尚未处理。
  • 203 非授权信息) 服务器已成功处理了请求,但返回的信息可能来自另一来源。
  • 204 无内容) 服务器成功处理了请求,但没有返回任何内容。
  • 205 重置内容) 服务器成功处理了请求,但没有返回任何内容。
  • 206 部分内容) 服务器成功处理了部分 GET 请求

3xx (重定向)

表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。 

  • 300 多种选择) 针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。
  • 301 永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
  • 302 临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
  • 303 查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。
  • 304 未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
  • 305 使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。
  • 307 临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。

4xx(请求错误) 

这些状态代码表示请求可能出错,妨碍了服务器的处理。

  • 400 错误请求) 服务器不理解请求的语法。
  • 401 未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
  • 403 禁止) 服务器拒绝请求。
  • 404未找到) 服务器找不到请求的网页。
  • 405 方法禁用) 禁用请求中指定的方法。
  • 406 不接受) 无法使用请求的内容特性响应请求的网页。
  • 407 需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。
  • 408 请求超时) 服务器等候请求时发生超时。

5xx(服务器错误)

这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。 

  • 500 服务器内部错误) 服务器遇到错误,无法完成请求。
  • 501 尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。
  • 502 错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
  • 503 服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
  • 504网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。
  • 505 HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本

未完待续...

  • 19
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: 根据引用,这份面试题涵盖了Vue.js的基础知识和高级概念,包括组件、生命周期、异步操作和跨域请求,以及Vue框架的优势、vue-router和服务端渲染(SSR)等。对于准备Vue.js面试的人来说,这份问题列表应该是非常有用的资源。 在回答你提到的其他问题之前,让我先回答第32和第33个问题。根据引用,GET请求和POST请求在底层都是基于TCP/IP协议实现的,都可以实现客户端和服务器端的双向交互。最本质的区别在于约定和规范。GET请求用于获取资源,进行查询操作,而POST请求用于传输实体对象,用于增删改操作。约定上,GET请求将参数拼接到URL上进行参数传递,而POST请求将参数写入请求正文中传递。这样的约定和规范有助于保持请求的语义和一致性。 关于第33个问题,数组去重,可以使用不同的方法来实现。一种常见的方法是使用Set数据结构,因为Set只会存储不重复的值。可以将数组转换为Set,然后再将Set转换回数组即可。另一种方法是使用循环和条件判断,遍历数组,将不重复的元素添加到一个新数组中。这样可以去除数组中的重复元素。 希望这些回答对你有帮助。如果你还有其他问题,请随时提问。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [2023前端vue高频面试题](https://blog.csdn.net/qq_27244301/article/details/129619172)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [2023最新高频前端面试题总结(附答案)](https://blog.csdn.net/jewels_w/article/details/125899379)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值