vue+react题集整理

2023-12-16 05:01:04

1.Typescript中 interface 和 type 的差别是什么?

interface只能用来描述对象类型

type可以描述任何类型组合

type后边需要有=

interface后边没有

当多次使用相同名称定义一个?interface?时,它们会自动合并为一个接口。同名属性的不能进行类型覆盖修改,否则编译不通过

type不支持声明合并,一个作用域内不允许有多个同名type

interface?可以被类实现(implements)和其他接口继承(extends),而?type?不具备这些能力。

interface也可以继承自type,但是只能是对象结构,或多个对象组成的交叉类型&的type

type可以通过&继承type或者interface得到交叉类型

2.vue中computed和watch区别

computed计算属性:依赖其他的值,有缓存,当它依赖的属性值发生改变,在下次获取computed的值时,才会重新计算computed值。

watch监听器:更多的是起到监听的作用,它没有缓存,每当监听的数据发生了变化都会执行回调进行后续的操作。

Computed:

支持缓存,当依赖的数据发生变化后,才会重新计算。

不支持异步操作,当它里面有异步操作时,无法监听数据的变化。

计算属性的值,默认会缓存,它是基于响应式依赖进行缓存的,就是基于data声明过或者从父组件传递过来的props中的数据进行计算。

如果一个属性是由其他属性计算而来的,那么一般就会使用计算属性。

如果计算属性的属性值是函数,那么默认会使用get方法,函数的返回值就是属性的属性值。在计算属性中,有get和set方法,当数据发生变化时,会调用set方法。

Watch:

不支持缓存,当数据发生变化时,他就会触发,之后进行对应的操作。

它支持异步监听。

监听的函数会接收两个参数,第一个参数是新值,第二个参数是旧值。

当一个属性发生变化时,就会执行对应的操作。

监听数据必须在data中声明或者是从父组件传递过来的props中的数据,当发生变化时,会触发对应的操作,函数有两个参数:

immediate:组件加载会直接触发回调函数。

deep:深度监听,发现数据内部的变化,在复杂数据类型中使用。

3.Umi中dva的工作流程是什么?

定义model:

创建一个model文件来定义应用程序中的数据模型,在model文件中,可以初始状态、监听器、异步请求等

引入model:

在入口文件(app.js/index.jsx)中引入定义的model

使用model:

在组件中使用connect方法连接model和组件,并将模型中的状态和action通过props传递给组件

触发action:

action在组件中,可以通过调用props中的函数来触发action,从而改变应用程序的状态

数据流更新:

当触发action时,dva会根据reducer和effect中的逻辑来更新数据模型的状态。触发reducer会同更新状态。而触发effect则可以进行异步操作,在异步操作完成之后再出发reducer来更新状态

4.如何理解事件循环?

事件循环是JavaScript实现异步的一种方法,也是JavaScript的执行机制。

事件循环又叫消息循环,是浏览器渲染主线程的工作方式。

因为 js 是单线程运行的,在代码执行时,通过将不同函数的执行上下文压入执行栈中来保证代码的有序执行。

先执行同步任务,如果遇到异步任务,js 引擎并不会一直等待其返回结果,而是会将这个任务挂起,交给其他线程去处理。自己继续执行执行栈中的其他同步任务。

当异步任务执行完毕后,再将异步任务对应的回调函数加入到一个任务队列中等待执行。

任务队列可以分为宏任务队列 和 微任务队列,当执行栈中的事件执行完毕后,js 引擎首先会判断微任务队列中是否有任务可以执行,如果有,就将微任务队首的事件压入栈中执行。队列遵循先进先出原则。

当微任务队列中的任务都执行完成后,再去执行宏任务队列中的任务。

如果宏任务队列中有微任务,继续执行微任务。如此反复循环,直至任务队列为空。这就是JavaScript的事件循环机制。

总结JS代码执行顺序:同步任务 => 微任务 => 宏任务。

所有的代码都要通过函数执行栈(主线程)中调用执行。

等到执行栈中的task执行完之后再回去执行任务队列之中的task。

任务队列中存放的是回调函数。

执行微任务过程中产生的新的微任务并不会推迟到下一个循环中执行,而是在当前的循环中继续执行。

当执行一个宏任务时,如果宏任务中产生了新的微任务,这些微任务不会立刻执行,而是会被放入到当前微任务队列中,在当前宏任务执行完毕后被依次执行。

5.vuex中的辅助函数怎么使用?

为了方便开发,提高代码的可读性和减少冗余代码,我们可以使用一些辅助函数

辅助函数包括mapState、mapGetters、mapMutations和mapActions。

mapState:通过这个函数,我们可以将store中的state映射到组件的computed计算属性中,从而实现对store中状态变量的访问。

mapGetters:通过这个函数,我们可以将store中的getters映射到组件的computed计算属性中,从而实现对store中计算状态的获取

mapMutations:通过这个函数,我们可以将store中的mutations映射到组件的methods方法中,从而实现对store中状态变量的修改

mapActions:通过这个函数,我们可以将store中的actions映射到组件的methods方法中,从而实现对store中异步操作的触发

6.前端性能优化,说出五条?

使用路由懒加载的方式

使用组件化

按需加载

给每一个列表项添加一个唯一标识

使用useMemo和useCallback

避免频繁的更新页面

减少不必要的嵌套,避免代码纵深层次过深,尽量扁平化

尽量减少重绘重排的次数

减少回流与重绘

减少iframe的使用

节流和防抖

7.Vue组件间通信方式都有哪些?

父组件向子组件传递数据 props

props只能是父组件向子组件进行传值,props使得父子组件之间形成一个单向的下行绑定。子组件的数据会随着父组件的更新而响应式更新。

子组件向父组件传递数据($emit的用法)

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

兄弟组件通信

A组件数据传递给共同的父组件 再有父组件接受后传递给B组件?

通过 $parent + $refs 以父组件为中间人来获取到兄弟组件,也可以进行通信

ref / $refs

ref:这个属性用在子组件上,它的用用就指向了子组件的实例,可以通过实例来访问组件的数据和方法

eventBus事件总线($emit / $on)

依赖注入(provide / inject)

$parent / $children

$children

$root

vuex

$attrs / $listeners

8.React中常用的Hooks方法及其含义,写出5个hooks?

useState:用于设置和使用组件的状态属性

useRef:可以将其绑定到DOM节点上,给DOM节点增加一个ref属性

useMemo:返回一个记忆函数

useCallback:为记忆函数,它可以防止因为组件重新渲染,导致方法被重新创建,起到缓存作用

useEffect:是副作用的钩子,可以实现特定的功能,如异步请求

9.TypeScript支持的访问修饰符有哪些?

public:公共修饰符,默认修饰符,可以在类的内部和外部访问。

private:私有修饰符,只能在类的内部访问,不能在类的外部访问。

protected:受保护修饰符,可以在类的内部和子类中访问,但不能在类的外部访问。

readonly:只读修饰符,只能在声明时或构造函数内部赋值,之后不可修改。

static:静态修饰符,用于定义类的静态成员,静态成员属于类本身而不是实例,可以直接通过类名访问。

10.封装一个使用递归方式的深拷贝方法?

function deepClone(obj) {
??// 检查是否为对象或数组
??if (typeof obj !== 'object' || obj === null) {
????return obj;
??}
??// 创建一个新对象或数组
??const clone = Array.isArray(obj) ? [] : {};
??// 遍历原对象或数组的所有属性
??for (let key in obj) {
????// 递归调用深拷贝方法
????clone[key] = deepClone(obj[key]);
??}
??return clone;
}

11.闭包的理解,优缺点,以及闭包的应用场景?

闭包是有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。使用闭包时,内部函数可以访问外部函数中的变量,因为内部函数作用域链中包括外部函数的作用域。

优点:

1.数据封装:闭包可以隐藏内部变量,只暴漏特定接口,实现数据的私有化和封装性,保护数据不受外部干扰。

2.记忆效应:闭包内的变量可以在函数调用结束后仍然保存存在,因而可以保存状态,记住上下文,实现类似于“记忆”效果,方便实现某些功能,如缓存、计数器等。

3.延长作用域链:闭包可以扩展函数的作用域链,使得内部函数可以访问外部函数的变量,灵活性更高。

缺点:

内存泄露:由于闭包会将他引用的外部变量保存在内存中,如果闭包被长时间持有且未释放。会导致内存泄露的问题。

性能消耗:闭包会占用较多的内存空间和计算资源,因为需要维护额外的作用域链和外部变量的引用。

对象状态的不确定性:闭包内的变量可能会被外部修改,这可能导致不可预料的结果。

应用场景:

实现模块化:闭包可以将变量和函数封装在一个独立的作用域中,实现模块化开发,避免全局命名冲突。

2.数据缓存和记忆化:利用闭包的记忆效应,可以实现一些缓存计算、避免重复计算的功能,提高代码性能。

3.封装私有变量:通过闭包,可以创建具有私有变量和方法的对象,实现面向对象的封装性。

4.事件处理和回调:在异步编程中,可以使用闭包来保存异步操作的上下文和状态,以便在回调函数中使用

12.Vue2和vue3的区别是什么?

vue2的双向数据绑定是利用了es5 的一个API Object.definepropert() 对数据进行劫持 结合发布订阅模式来实现的。vue3中使用了es6的proxyAPI对数据进行处理。

相比与vue2,使用proxy API 优势有:defineProperty只能监听某个属性,不能对全对象进行监听;可以省去for in 、闭包等内容来提升效率(直接绑定整个对象即可);可以监听数组,不用再去单独的对数组做特异性操作,vue3可以检测到数组内部数据的变化。

vue2不支持碎片。vue3支持碎片

vue2使用选项类型api,选项型api在代码里分割了不同的属性:data,computed,methods等

vue3使用合成型api,新的合成型api能让我们使用方法来分割,相比于旧的api使用属性来分组,这样代码会更加简便和整洁

生命周期钩子函数不同

13.双向数据绑定原理,谈一谈你对它的理解?

单向绑定非常简单,就是把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新

双向绑定就很容易联想到了,在单向绑定的基础上,用户更新了View,Model的数据也自动被更新了,这种情况就是双向绑定

Vue 是数据双向绑定的框架,双向绑定由三个重要部分构成

数据层(Model):应用的数据及业务逻辑

视图层(View):应用的展示效果,各类UI组件

业务逻辑层(ViewModel):框架封装的核心,它负责将数据与视图关联起来

实现双向绑定流程:

1.new Vue()首先执行初始化,对data执行响应化处理,这个过程发生Observe中

2.同时对模板执行编译,找到其中动态绑定的数据,从data中获取并初始化视图,这个过程发生在Compile中

3.同时定义?个更新函数和Watcher,将来对应数据变化时Watcher会调用更新函数

4.由于data的某个key在?个视图中可能出现多次,所以每个key都需要?个管家Dep来管理多个Watcher

5.将来data中数据?旦发生变化,会首先找到对应的Dep,通知所有Watcher执行更新函数

14.Vue常用的修饰符有哪些?分别有什么应用场景?

表单修饰符

Lazy:光标离开标签的时候,才会将值赋予给value,也就是在change事件之后再进行信息同步

Trim:自动过滤用户输入的首空格字符,而中间的空格不会过滤

Number:自动将用户的输入值转为数值类型,但如果这个值无法被parseFloat解析,则会返回原来的值

事件修饰符

Stop:阻止了事件冒泡,相当于调用了event.stopPropagation方法

Prevent:阻止了事件的默认行为,相当于调用了event.preventDefault方法

Self:只当在 event.target 是当前元素自身时触发处理函数

Once:绑定了事件以后只能触发一次,第二次就不会触发

Capture:使事件触发从包含这个元素的顶层开始往下触发

Passive:在监听元素滚动事件的时候,会一直触发onscroll事件会让我们的网页变卡,因此我们使用这个修饰符的时候,相当于给onscroll事件整了一个.lazy修饰符

Native:让组件变成像html内置标签那样监听根元素的原生事件,否则组件上使用 v-on 只会监听自定义事件

鼠标按键修饰符

left 左键点击

right 右键点击

middle 中键点击

键值修饰符

普通键(enter、tab、delete、space、esc、up…)

系统修饰键(ctrl、alt、meta、shift…)

v-bind修饰符

Async:能对props进行一个双向绑定

Prop:设置自定义标签属性,避免暴露数据,防止污染HTML结构

Camel:将命名变为驼峰命名法,如将view-Box属性名转换为 viewBox

应用场景:

.stop:阻止事件冒泡

.native:绑定原生事件

.once:事件只执行一次

.self :将事件绑定在自身身上,相当于阻止事件冒泡

.prevent:阻止默认事件

.caption:用于事件捕获

.once:只触发一次

.keyCode:监听特定键盘按下

.right:右键

15.说说 Vue 中 CSS scoped 的原理?

当一个style标签拥有scoped属性时,它的CSS样式就只能作用于当前的组件,也就是说,该样式只能适用于当前组件元素。通过该属性,可以使得组件之间的样式不互相污染。如果一个项目中的所有style标签全部加上了scoped,相当于实现了样式的模块化。

vue中的scoped属性的效果主要通过PostCSS转译实现

PostCSS给一个组件中的所有dom添加了一个独一无二的动态属性,然后,给CSS选择器额外添加一个对应的属性选择器来选择该组件中dom,这种做法使得样式只作用于含有该属性的dom——组件内部dom。

16.为什么Vue中的v-if和v-for不建议一起用?

当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。这意味着 v-if 将分别重复运行于 每个 v-for 循环中,即先运行 v-for 的循环,然后在每一个 v-for 的循环中,再进行 v-if 的条件对比,会造成性能问题,影响速度。

解决方案:

可以用计算属性代替

<template>
??<div>
????<ul>
??????<li v-for="user in activeUsers" :key="user.id">{{ user.name }}</li>
????</ul>
??</div>
</template>

<script>
??export default {
????// ...
????computed: {
??????activeUsers() {
????????return this.users.filter((user) => user.isActive)
??????}
????}
??}
</script>
}

文章来源:https://blog.csdn.net/m0_74060440/article/details/134935698
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。