2023年最新前端面试题汇总大全二(含答案超详细,Vue,TypeScript,React,微信小程序,Webpack 汇总篇)-- 持续更新 1

本文涉及的产品
云解析DNS,个人版 1个月
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 2023年最新前端面试题汇总大全二(含答案超详细,Vue,TypeScript,React,微信小程序,Webpack 汇总篇)-- 持续更新

1. 谈谈你对MVVM开发模式的理解?

MVVM是一种简化用户界面的实践驱动编程方式。在当前主流的前后端分离的开发模式中,MVVM模式的优越性日益体现,相较于经典的MVC模式,其对于程序模块的封装很好地解决了前后端信息交互的冗余和繁琐


MVVM分为Model、View、ViewModel三者。

Model 代表数据模型,数据和业务逻辑都在Model层中定义;

View 代表UI视图,负责数据的展示;

ViewModel 负责监听 Model 中数据的改变并且控制视图的更新,处理用户交互操作;

Model 和 View 并无直接关联,而是通过 ViewModel 来进行联系的,Model 和 ViewModel 之间有着双向数据绑定的联系。因此当 Model 中的数据改变时会触发 View 层的刷新,View 中由于用户交互操作而改变的数据也会在 Model 中同步。

这种模式实现了 Model 和 View 的数据自动同步,因此开发者只需要专注对数据的维护操作即可,而不需要自己操作 dom。


为什么使用MVVM:低耦合,可复用,独立开发,可测试


2. v-if 和 v-show 有什么区别?

手段

v-if是动态的向DOM树内添加或者删除DOM元素;

v-show是通过设置DOM元素的display样式属性控制显隐;

编译

v-if是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译;

v-show是在任何条件下,无论首次条件是否为真,都被编译,然后被缓存,而且DOM元素保留;

性能消耗:

v-if有更高的切换消耗;

v-show有更高的初始渲染消耗

3.r o u t e 和 route和route和router区别

$route 是“路由信息对象”,包括 path,params,hash,query,fullPath,matched,name 等路由信息参数

$router 是“路由实例”想要导航到不同URL 对象包括了路由的跳转方法,钩子函数等。通过push、replace、go、back等方法,来实现页面间的跳转

4.vue自定义指令

vue指令


vue2


局部注册:directive选项

directives: {
 'focus': {
   bind(el, binding, vnode) {
     el.focus()
   }
 }
}

全局注册:main.js

Vue.directives('focus',{
  bind(el, binding, vnode) {
     el.focus()
   }
})

生命周期:


bind:只调用一次,指令第一次绑到元素调用,用于初始化

inserted:被绑定元素插入父节点时调用

update:所在组件vnode更新调用

componentUpdate:指令在组件的vnode及子组件的vnode全部更新完调用

ubind:只调用一侧,指令解绑

vue3


局部注册:引入 import { Directive , DirectiveBinding } from ‘vue’ 分别校验vFocus,binding

<template>
<input type="text" v-focus="{ color: 'red' }" />
</template>
<script setup>
const vFocus = {
created(el, binding) {
 el.style.backgroundColor = binding.value.color;
 console.log(el, binding.value.color); //<input type="text" style="background-color: red;"> 'red'
},
};
</script>

全局注册:main.js,app.vue如上引入

import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.directive('focus', {
 created(el, binding) {
     el.style.backgroundColor = binding.value.color;
     console.log(el, binding.value.color); //<input type="text" style="background-color: red;"> 'red'
 }
})
app.mount('#app')

生命周期:


created 元素初始化的时候

beforeMount 指令绑定到元素后调用 只调用一次

mounted 元素插入父级dom调用

beforeUpdate 元素被更新之前调用

update 这个周期方法被移除 改用updated

beforeUnmount 在元素被移除前调用

unmounted 指令被移除后调用 只调用一次

5.vue项目优化

代码层面

长列表性能优化

事件销毁, beforeDestroy生命周期函数内执行销毁逻辑。

图片懒加载

路由懒加载

按需加载插件

v-if,v-for避免同时使用

v-if,v-show选择

keep-alive组件缓存

input防抖节流

基础的web技术优化

开启gzip压缩

浏览器缓存

CDN加速

webpack优化

6.vue模板如何编译

Vue的模板编译就是将“HTML”模板编译成render函数的过程。这个过程大致可以分成三个阶段:


解析阶段:将“HTML”模板解析成AST语法树;

核心 parseHTML( template ,{}) Vue定义了很多匹配HTML的正则表达式 ,parseHTML根据正则匹配

parseHTML是解析模板字符串的“主线程”,它的第一个参数是要解析的模板字符串, 也就是单文件组件中最外层 所包裹的部分;第二个参数是一个选项对象,它会包含一些回调,以及一些配置项。

选项对象:

start( tag, attrs, unary ) 匹配到开始标签时的回调,tag为当前标签的标签名,attrs为该标签上的属性列表,unary为当前标签是否为自闭合标签

end() 匹配到结束标签时的回调

chars(text) 匹配到文本节点的回调

comment(text) 匹配到注释节点的回调,其处理逻辑跟文本的处理逻辑类似

优化阶段:从AST语法树中找出静态子树并进行标记(被标记的静态子树在虚拟dom比对时会被忽略,从而提高虚拟dom比对的性能);

上面简单介绍过,优化阶段的工作就是标记静态子树,标记静态子树后主要有以下两个优点:

生成虚拟dom的过程中,如果发现一个节点是静态子树,除了首次渲染外不会生成新的子节点树,而是拷贝已存在的静态子树;

比对虚拟dom的过程中,如果发现当前节点是静态子树,则直接跳过,不需要进行比对。

标记静态子树的过程分为两个步骤:

遍历AST语法树,找出所有的静态节点并打上标记(注:当前节点及其所有子节点都是静态节点,当前节点才会被打上静态节点的标记)

遍历经过上面步骤后的树,找出静态根节点,并打上标记(注:静态根节点是指本身及所有子节点都是静态节点,但是父节点为动态节点的节点,找到了静态根节点也就找到了“静态子树”)

代码生成阶段:通过AST生成代码字符串,并最终生成render函数。

7.vue2响应式原理

vue 采用了几个核心部件 : Observer ,Dep, Watcher ,Scheduler


observer把一个普通的对象转换成响应式的对象

observer 把对象的每个属性通过 object.defineProperty 转换为带有 getter 和 setter 的属性

Dep 表示依赖, vue 会为响应式对象中的每一个属性,对象本身,数组本身创建一个 dep 实例,每个 dep 实例都可以做两件事情 :

记录依赖:是谁在用我

派发更新:我变了,我要通知那些用我的人

watcher 在函数执行的过程中,如果发生了依赖记录,那么 dep 就会把这个全局变量记录下来,表示有一个 wathcer 用到了我这个属性。

Scheduler 不会立即执行更新,通过nexttick异步更新

8.vue3响应式原理

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


通过Reffect(反射): 对源对象的属性进行操作, Reflect不是一个函数对象,因此它是不可构造的。


9.刷新浏览器后,Vuex的数据是否存在?如何解决?

不存在


原因: 因为 store 里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,store里面的数据就会被重新赋值初始化。


我们有两种方法解决该问题:


使用 vuex-along

使用 localStorage 或者 sessionStroage

10.vue和react共同点?区别

共同点:


数据驱动视图

组件化

都使用 Virtual DOM

不同点:


核心思想不同

vue定位就是尽可能的降低前端开发的门槛,让更多的人能够更快地上手开发。这就有了vue的主要特点:灵活易用的渐进式框架,进行数据拦截/代理,它对侦测数据的变化更敏感、更精确。

react 定位就是提出 UI 开发的新思路 React推崇函数式编程(纯组件),数据不可变以及单向数据流,当然需要双向的地方也可以手动实现, 比如借助onChange和setState来实现。

组件写法

React推荐的做法是JSX + inline style, 也就是把 HTML 和 CSS 全都写进 JavaScript 中

Vue 推荐的做法是 template 的单文件组件格式(简单易懂,从传统前端转过来易于理解),即 html,css,JS 写在同一个文件(vue也支持JSX写法)

diff算法

响应式原理

vue2采用object.defineProperty ,vue3采用proxy,reflect

React基于状态机,手动优化,数据不可变,需要setState驱动新的state替换老的state。

11.vue双向数据绑定原理

简易实现:v-model分为两部分,通过v-bind绑定值,再通过v-on:input来通步修改值


原理:


需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上setter和getter这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化

通过dep来理清依赖关系,watcher在依赖中添加自身

compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图

待属性变动dep.notice()通知时,能调动watcher自身的update方法,并处罚compile回调渲染视图

12.computed和watch区别

computed计算属性,watch监听属性


计算属性不在 data 中,它是基于data 或 props 中的数据通过计算得到的一个新值。watch 可以监听的数据来源:data,props,computed内的数据

component中有get和set方法,会默认缓存计算结果。watch不支持缓存,支持异步, immediate监听属性立即执行一次,deep开启深度监听

13.Vuex

Vuex是一种状态管理模式,存在的目的是共享可复用的组件状态。


主要包括以下几个模块:


State => 基本数据,定义了应用状态的数据结构,可以在这里设置默认的初始状态。

Getter => 从基本数据派生的数据,允许组件从 Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性。

Mutation => 是唯一更改 store 中状态的方法,且必须是同步函数。

Action => 像一个装饰器,包裹mutations,使之可以异步。用于提交 mutation,而不是直接变更状态,可以包含任意异步操作。

Module => 模块化Vuex,允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中。

14.vuex辅助函数

mapState, mapMutations, mapActions, mapGetters


mapState和mapGetters:


两者都放在 computed中,以mapState举例

import { mapState } from 'vuex'

import { mapState } from 'vuex'
computed中
computed:{
  ...mapState(['data'])  //data是vuex存放的state中的属性,此时{{data}}可使用
}

mapMutations, mapActions:


放在组件的methods属性中 。使用与上类似

15.vuex模块化使用

当我们开发的项目比较大时,store中的数据就可能比较多,这时我们store中的数据就可能变得臃肿,为了解决这一问题,我们就需要将store模块化(module)


前提:创建两份js文件,含有属性与vuex写法相同,需要通过 namespaced:true开启命名空间store/index.js:在modules中引入文件


使用:


访问state数据:

第一种方式:this.$store.state.moduleA.sum

第二种方式: ...mapState('moduleA',['sum','number'])

action提交mutation

第一种方式:需要传参this.store.dispatch(′moduleB/addZhang′,name:′小明′,age:18),无需传参this.store.dispatch('moduleB/addZhang',{name:'小明',age:18}) ,无需传参this.store.dispatch('moduleB/addServer')

第二种方式:...mapActions('moduleB',['addZhang'])

getters计算属性

第一种方式: this.$store.getters['moduleB/firstName']

第二种方式:...mapGetters('moduleB',['firstName'])

16.vue中mixin

mixin(混入): 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。


本质其实就是一个js对象,它可以包含我们组件中任意功能选项,如data、components、methods 、created、computed等等


我们只要将共用的功能以对象的方式传入 mixins选项中,当组件使用 mixins对象时所有mixins对象的选项都将被混入该组件本身的选项中来


具体使用:


创建mixins.js文件

let mixin = {
    created() {
        console.log('我是mixin中的');
    },
    methods: {
        hellow() {
            console.log('你好');
        },
    },
}
export default mixin

局部使用

import mixin from "./mixins";
export default {
  mixins: [mixin],
  mounted() {
    this.hellow();//你好
  },
};

全局使用main.js

import { createApp } from 'vue'
import App from './App.vue'
import mixins from "./mixins";
const app = createApp(App)
app.mixin(mixins)
app.mount('#app')

17.Vue中给对象添加新属性时,界面不刷新怎么办?

原因:vue2响应式采用object.defineProperty进行劫持,那个添加新属性时,新的属性不会具有get和set方法,不是一个响应式所以界面不刷新


解决:Vue.set() 向响应式对象中添加一个property,并确保这个新 property 同样是响应式的


vue3通过proxy劫持和reflect映射实现响应式,不会有这个问题


18.vue组件通讯方式

通过 props 传递

props校验:name:{type:String,required:true,default:默认值} required是否必要

通过 $emit 触发自定义事件

使用 ref

EventBus

Provide 与 Inject

Vuex

19.vue3setup的父传子怎么去写?

介绍三种方法:


第一种:使用vue2写法通过props和$emit


第二种:setup函数写法


setup(props,context),通过props接收数据,通过context.emit(‘调用父组件方法’,传递参数)

第三种:script中setup

const emits = defineEmits(["changeNumber"]);
// 也可以不赋值,取值通过{{num}}获取
const props = defineProps({
  num: {
    type: Number,
    default: () => [],
  },
  list: {
    type: Array,
  },
});
const changeNum = function () {
  emits("changeNumber", 888);
  //   console.log(11111111111);
};

20.setup可不可以直接写async和await?

可以


setup 语法糖中可直接使用 await,不需要写 async , setup 会自动变成 async setup

<script setup>
  import Api from '../api/Api'
  const data = await Api.getData()
  console.log(data)
</script>

21.vue生命周期

vue2


f9c692f63fb84948b79a5de9bd173ee0.png


beforeCreate – 首次访问data


created – 首次访问this生命周期


mounted – 页面展示


vue3

863ebacfed9644d49a0ea1182b5b165b.png



区别:


beforeCreate -> setup() 开始创建组件之前,创建的是data和method

created -> setup()

beforeMount -> onBeforeMount 组件挂载到节点上之前执行的函数。

mounted -> onMounted 组件挂载完成后执行的函数

beforeUpdate -> onBeforeUpdate 组件更新之前执行的函数。

updated -> onUpdated 组件更新完成之后执行的函数。

beforeDestroy -> onBeforeUnmount 组件挂载到节点上之前执行的函数。

destroyed -> onUnmounted 组件卸载之前执行的函数。dszhuoyi

activated -> onActivated 组件卸载完成后执行的函数

deactivated -> onDeactivated

22.说说 Vue 中 CSS scoped 的原理

添加scoped标签后会给组件中所有标签元素,添加一个唯一标识,这个唯一标识就是自定义属性,data-v-xxxxxxxx这样的字眼,同时对应的样式选择器也会添加这个唯一的属性选择器


23.$nextTick原理

在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM


nextTick原理


24.data是函数不是对象

vue是一个单页面应用最终所有的实例都会挂载到app.vue文件,如果data是一个对象那么会导致数据污染。通过函数返回对象的方式,利用函数作用域的限制避免数据污染


25.路由守卫

vue路由守卫分为三种:全局路由守卫,独享路由守卫,组件路由守卫


to: 进入到哪个路由去


from: 来自哪个路由


next:是否跳转


全局守卫: router.beforeEach((to,from,next)=>{})

独享路由守卫: beforeEnter:(to,from,next)=>{}

组件路由守卫: beforeRouteEnter:(to,from,next)=>{}, beforeRouteUpdate , beforeRouteLeave

目录
相关文章
|
11天前
|
小程序
Taro@3.x+Vue@3.x+TS开发微信小程序,设置转发分享
本文介绍了Taro中`useShareAppMessage`的使用方法,需在页面配置`enableShareAppMessage: true`并重新编译。
Taro@3.x+Vue@3.x+TS开发微信小程序,设置转发分享
|
11天前
|
小程序 数据安全/隐私保护
Taro@3.x+Vue@3.x+TS开发微信小程序,网络请求封装
在 `src/http` 目录下创建 `request.ts` 文件,并配置 Taro 的网络请求方法 `Taro.request`,支持多种 HTTP 方法并处理数据加密。
Taro@3.x+Vue@3.x+TS开发微信小程序,网络请求封装
|
11天前
|
小程序
Taro@3.x+Vue@3.x+TS开发微信小程序,上传文件
本文介绍如何在Taro项目中使用Nut UI的`&lt;nut-uploader/&gt;`组件实现图片上传功能,并通过示例代码展示了自定义上传逻辑的方法。
Taro@3.x+Vue@3.x+TS开发微信小程序,上传文件
|
9天前
|
前端开发 Java Spring
Spring与Angular/React/Vue:当后端大佬遇上前端三杰,会擦出怎样的火花?一场技术的盛宴,你准备好了吗?
【8月更文挑战第31天】Spring框架与Angular、React、Vue等前端框架的集成是现代Web应用开发的核心。通过RESTful API、WebSocket及GraphQL等方式,Spring能与前端框架高效互动,提供快速且功能丰富的应用。RESTful API简单有效,适用于基本数据交互;WebSocket支持实时通信,适合聊天应用和数据监控;GraphQL则提供更精确的数据查询能力。开发者可根据需求选择合适的集成方式,提升用户体验和应用功能。
39 0
|
9天前
|
前端开发 Java JSON
Struts 2携手AngularJS与React:探索企业级后端与现代前端框架的完美融合之道
【8月更文挑战第31天】随着Web应用复杂性的提升,前端技术日新月异。AngularJS和React作为主流前端框架,凭借强大的数据绑定和组件化能力,显著提升了开发动态及交互式Web应用的效率。同时,Struts 2 以其出色的性能和丰富的功能,成为众多Java开发者构建企业级应用的首选后端框架。本文探讨了如何将 Struts 2 与 AngularJS 和 React 整合,以充分发挥前后端各自优势,构建更强大、灵活的 Web 应用。
19 0
|
9天前
|
前端开发 UED 开发者
React组件优化全攻略:深度解析让你的前端应用飞速运行的秘诀——从PureComponent到React.memo的彻底性能比较
【8月更文挑战第31天】在构建现代Web应用时,性能是提升用户体验的关键因素。React作为主流前端库,其组件优化尤为重要。本文深入探讨了React组件优化策略,包括使用`PureComponent`、`React.memo`及避免不必要的渲染等方法,帮助开发者显著提升应用性能。通过实践案例对比优化前后效果,不仅提高了页面渲染速度,还增强了用户体验。优化React组件是每个开发者必须关注的重点。
20 0
|
9天前
|
前端开发 JavaScript 大数据
React与Web Workers:开启前端多线程时代的钥匙——深入探索计算密集型任务的优化策略与最佳实践
【8月更文挑战第31天】随着Web应用复杂性的提升,单线程JavaScript已难以胜任高计算量任务。Web Workers通过多线程编程解决了这一问题,使耗时任务独立运行而不阻塞主线程。结合React的组件化与虚拟DOM优势,可将大数据处理等任务交由Web Workers完成,确保UI流畅。最佳实践包括定义清晰接口、加强错误处理及合理评估任务特性。这一结合不仅提升了用户体验,更为前端开发带来多线程时代的全新可能。
16 0
|
9天前
|
前端开发 JavaScript 测试技术
React 与前端自动化测试也太重要啦!各种测试框架助力确保应用质量,快来开启优质开发之旅!
【8月更文挑战第31天】随着前端技术的发展,React 成为了构建用户界面的热门选择。然而,随着应用复杂性的增加,确保应用质量变得至关重要。本文介绍了前端自动化测试的重要性,并详细综述了常用的测试框架如 Jest、Enzyme 和 Cypress,以及如何通过它们进行高效的 React 组件测试。通过遵循最佳实践,如编写可维护的测试用例、覆盖关键场景、集成 CI/CD 流程和进行性能测试,可以显著提高应用的稳定性和可靠性。
18 0
|
10天前
|
JavaScript 前端开发 测试技术
Vue.js开发者必看!Vue Test Utils携手端到端测试,打造无懈可击的应用体验,引领前端测试新风尚!
【8月更文挑战第30天】随着Vue.js的普及,构建可靠的Vue应用至关重要。测试不仅能确保应用质量,还能提升开发效率。Vue Test Utils作为官方测试库,方便进行单元测试,而结合端到端(E2E)测试,则能构建全面的测试体系,保障应用稳定性。本文将带你深入了解如何使用Vue Test Utils进行单元测试,通过具体示例展示如何测试组件行为;并通过Cypress进行E2E测试,确保整个应用流程的正确性。无论是单元测试还是E2E测试,都能显著提高Vue应用的质量,让你更加自信地交付高质量的应用。
21 0
|
20天前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
下一篇
DDNS