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

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 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

目录
相关文章
|
1月前
|
前端开发 JavaScript 开发者
React与Vue:前端框架的巅峰对决与选择策略
【10月更文挑战第23天】React与Vue:前端框架的巅峰对决与选择策略
|
1月前
|
前端开发 JavaScript
手敲Webpack 5:React + TypeScript项目脚手架搭建实践
手敲Webpack 5:React + TypeScript项目脚手架搭建实践
|
1月前
|
前端开发 JavaScript 数据管理
React与Vue:两大前端框架的较量与选择策略
【10月更文挑战第23天】React与Vue:两大前端框架的较量与选择策略
|
1月前
|
JavaScript 前端开发 搜索推荐
Vue的数据驱动视图与其他前端框架的数据驱动方式有何不同?
总的来说,Vue 的数据驱动视图在诸多方面展现出独特的优势,其与其他前端框架的数据驱动方式的不同之处主要体现在绑定方式、性能表现、触发机制、组件化结合、灵活性、语法表达以及与后端数据交互等方面。这些差异使得 Vue 在前端开发领域具有独特的地位和价值。
|
2月前
|
JavaScript 前端开发 算法
前端优化之超大数组更新:深入分析Vue/React/Svelte的更新渲染策略
本文对比了 Vue、React 和 Svelte 在数组渲染方面的实现方式和优缺点,探讨了它们与直接操作 DOM 的差异及 Web Components 的实现方式。Vue 通过响应式系统自动管理数据变化,React 利用虚拟 DOM 和 `diffing` 算法优化更新,Svelte 通过编译时优化提升性能。文章还介绍了数组更新的优化策略,如使用 `key`、分片渲染、虚拟滚动等,帮助开发者在处理大型数组时提升性能。总结指出,选择合适的框架应根据项目复杂度和性能需求来决定。
|
2月前
|
前端开发 JavaScript 安全
在vue前端开发中基于refreshToken和axios拦截器实现token的无感刷新
在vue前端开发中基于refreshToken和axios拦截器实现token的无感刷新
156 4
|
2月前
|
JavaScript 前端开发 Python
django接收前端vue传输的formData图片数据
django接收前端vue传输的formData图片数据
63 4
|
2月前
|
JavaScript 前端开发 Java
VUE学习四:前端模块化,ES6和ES5如何实现模块化
这篇文章介绍了前端模块化的概念,以及如何在ES6和ES5中实现模块化,包括ES6模块化的基本用法、默认导出与混合导出、重命名export和import,以及ES6之前如何通过函数闭包和CommonJS规范实现模块化。
115 0
VUE学习四:前端模块化,ES6和ES5如何实现模块化
|
2月前
|
JavaScript 前端开发 网络架构
|
1月前
|
前端开发 JavaScript 开发者
React与Vue:前端框架的巅峰对决与选择策略
【10月更文挑战第23天】 React与Vue:前端框架的巅峰对决与选择策略