初级前端面试
面试题
1、区别:VUE2与VUE3
Vue3相比于Vue2有以下一些不同之处:
- 性能提升:Vue3通过重写虚拟DOM的实现方式,使得渲染性能提升了许多。同时,Vue3还对组件的初始化和更新过程进行了优化,提升了整体的性能表现。
- Composition API:Vue3引入了Composition API,让开发者可以更方便地组织组件内部的逻辑。相较于Vue2的Options API,Composition API更加灵活、可读性更高。
- TypeScript支持:Vue3对TypeScript的支持更加友好,提供了更多的类型定义和类型推断功能。
- 新的API:Vue3引入了很多新的API,例如
Teleport
、Suspense
等,为开发者提供了更多的组件化方案。
2、描述一下vue2、vue3、react的diff算法
Vue2中的diff算法是采用双端指针的方式进行比较的,通过同层级的节点进行比较,如果在比较过程中出现了不一致,则使用key属性进行新旧节点的区分,如果key也不一致,则直接将旧节点删除,加入新节点。这种算法的效率较低,因为需要遍历整个树结构进行比较。
Vue3中的diff算法采用了前后指针以及双端队列,通过将树结构转换为一个数组,然后通过前后指针进行比较。这种算法的效率较高,因为避免了对整个树结构的遍历。
React中的diff算法是采用虚拟DOM的方式进行比较的,通过比较新旧虚拟DOM的差异性,然后只对差异进行更新,而不是对整个树结构进行更新。这种算法的效率也较高,因为只需要比较差异部分。
3、vue和react的区别
Vue和React的区别主要有以下几点:
- 模板和JSX的差异:Vue使用模板语法来描述组件,而React使用JSX语法。模板语法更加易于理解和阅读,但是在一些复杂的情况下可能会出现问题。JSX语法更加灵活,但是需要掌握一定的JavaScript语言基础。
- 状态管理的差异:Vue使用Vuex来管理状态,而React使用Redux或者Context API来管理状态。Vuex在处理大型应用的时候会更加方便,而Redux在处理多个组件之间的通信时会更加方便。
- 组件化的差异:Vue的组件化方案更加完整,包括了组件的模板、样式和逻辑。React的组件化方案更加灵活,可以根据需要自由组合组件。
- 生态圈的差异:Vue的生态圈相对于React来说要小一些,但是社区质量较高。React的生态圈更加庞大,但是质量参差不齐。
- 学习曲线的差异:Vue的学习曲线相对于React来说要低一些,因为Vue的API设计更加易于理解和使用。React的学习曲线相对较高,需要掌握一些JavaScript的基础知识。
4、react常用hooks,以及周边的东西。比如antd之类的,你不是写过组件库吗,是怎么设计的。
设计组件库时,React Hooks 是一个非常有用的特性。它可以使组件的逻辑更加清晰和易于维护,同时也可以使代码更加简洁和可读。
在设计组件库时,需要考虑以下几个方面:
- 复用性:组件库中的每个组件都应该具有较高的复用性,可以在多个项目中使用。
- 可定制性:组件库中的每个组件都应该具有一定的可定制性,可以根据不同的需求进行调整。
- 易用性:组件库中的每个组件都应该易于使用,并且可以通过文档进行详细的说明和演示。
- 性能:组件库中的每个组件都应该具有良好的性能表现,可以在大型应用中使用,而不会影响用户的体验。
- 风格一致性:组件库中的每个组件都应该具有一致的风格和设计,可以使整个应用看起来更加统一和美观。
在使用 React Hooks 设计组件库时,可以考虑以下几个常用的 Hooks:
- useState:用于管理组件的状态,可以使组件更加灵活和易于维护。
- useEffect:用于处理组件的副作用,例如订阅事件、发送请求等。
- useContext:用于管理组件的上下文,可以使多级嵌套的组件之间更加方便地进行通信。
- useReducer:用于管理组件的状态,可以使组件更加灵活和易于维护。
- useCallback:用于缓存函数,可以提高组件的性能表现。
以上是一些常用的 Hooks,但是在设计组件库时,还需要考虑到每个组件的具体需求,选择适合的 Hooks 进行设计。
5、useEfect useLayoutEfect的区别,这两个哪个先执行(执行时机),分别用于哪些场景
useEffect
和useLayoutEffect
都是React中用于处理副作用的Hooks,在执行时机和场景上有一些不同:
- 执行时机:
useEffect
是在浏览器渲染完成后执行的,而useLayoutEffect
是在浏览器渲染之前执行的。 - 场景:
useEffect
适用于处理异步数据请求、事件订阅等副作用,而useLayoutEffect
适用于处理DOM相关的副作用,例如测量DOM节点的尺寸、计算布局等。
在使用时,一般情况下可以优先使用useEffect
,因为它的执行时机更加符合常规的使用场景。只有在需要在浏览器渲染之前执行一些操作时,才需要使用useLayoutEffect
。
6、简述fiber
Fiber是React中的一种新的协调机制,用于在渲染过程中处理异步任务和优先级,从而提高渲染的性能和流畅度。
传统的渲染机制是基于递归的,并且是同步执行的。这种机制在处理大量的DOM节点时会导致性能问题,因为递归的过程无法中断,无法处理优先级等问题。而Fiber则采用了一种类似于链表的方式进行渲染,可以在渲染过程中处理异步任务和优先级,并且可以随时中断和恢复渲染,从而提高整体的性能表现。
在React中,Fiber的实现主要包含了以下几个部分:
- Fiber节点:代表组件树中的一个节点,包含了组件的状态和更新信息。
- Fiber链表:将整个组件树转换为一个链表结构,用于处理异步任务和优先级。
- 任务调度器:负责处理异步任务和优先级,将任务按照优先级进行排序,并根据需要中断和恢复渲染过程。
- 副作用链表:用于处理组件的副作用,例如DOM操作、事件订阅等。
通过Fiber的实现,React可以更加高效地处理异步任务和优先级,从而提高整体的性能表现。同时,Fiber的设计也为React未来的发展提供了更多的可能性,例如增加对并发模式的支持等。
7、vue的watch和watchEffect的区别,应用场景
watch
和watchEffect
都是Vue中用于监听数据变化的方法,它们的区别如下:
watch
是一个选项,需要在组件的选项中进行设置,可以监听到指定数据的变化,并在回调函数中做出相应的操作。watch
可以监听到对象、数组、深度嵌套的数据等,使用范围较广。
watchEffect
是一个函数,可以监听到函数内部使用到的数据变化,并在回调函数中做出相应的操作。watchEffect
只能监听到基本数据类型、ref、reactive等响应式数据类型,但是由于它可以自动追踪数据的变化,因此使用起来更加方便。
应用场景方面,watch
适合监听对象、数组等复杂数据类型的变化,需要进行一些复杂的操作时使用。watchEffect
适合监听基本数据类型、ref、reactive等响应式数据类型的变化,需要进行简单的操作时使用。
在实际开发中,可以根据具体的需求选择适合的方法进行监听。
8、简述nextTick,nextTick能用setTImeOut代替吗?为什么。你在哪些场景用nextTick,其实就是在考 event loop、宏任务、微任务
nextTick
是 Vue 中用于异步执行回调函数的方法,它的本质是利用了 JavaScript 中的事件循环机制,将回调函数放入微任务队列中,在下一个事件循环周期中异步执行。
nextTick
不能用 setTimeout
来代替。因为 nextTick
是利用了事件循环的机制,将回调函数放入微任务队列中,而 setTimeout
则是利用了宏任务队列的机制,将回调函数放入宏任务队列中。在事件循环中,微任务的优先级高于宏任务,因此 nextTick
能够保证回调函数在下一个事件循环周期中尽快地执行,而 setTimeout
则无法保证。
nextTick
的主要应用场景是在 Vue 中更新 DOM 后,需要执行一些操作,例如获取 DOM 元素的位置、计算元素的尺寸等。由于 Vue 的数据绑定是异步更新的,所以更新 DOM 后需要等待下一个事件循环周期才能获取正确的结果。
除了 nextTick
,在 JavaScript 中还有其他的微任务,例如 Promise.then
、MutationObserver
等。在使用时,需要根据具体的场景选择适合的方法,在保证性能的前提下尽可能地减少页面的重绘和回流。
9、vite和webpack的区别
vite 和 webpack 都是前端构建工具,它们的区别主要有以下几点:
- 打包方式不同:vite 是一种基于 ES Modules 的打包方式,可以快速地构建开发环境,而 webpack 是一种基于 CommonJS 的打包方式,构建速度相对较慢。
- 热更新方式不同:vite 使用了浏览器原生的 ES Modules 特性,可以实现更加快速的热更新,而 webpack 则需要借助插件来实现热更新。
- 代码分割方式不同:vite 可以通过 import() 方式来实现代码分割,而 webpack 则需要使用动态 import 或者 require.ensure 来实现代码分割。
- 插件生态不同:vite 的插件生态相对较新,但是已经拥有了一些常用的插件,而 webpack 的插件生态相对较成熟,可以满足绝大部分的需求。
- 构建速度不同:由于采用了不同的打包方式和热更新方式,vite 的构建速度要比 webpack 快很多。
总的来说,vite 更加适合于开发环境下的快速构建,而 webpack 则更加适合于生产环境下的稳定构建。在实际开发中,可以根据具体的需求选择适合的构建工具。
10、简述一下递归,以及你在项目哪些地方用了,怎么使用的
递归是一种算法,通常用于解决可以分解为相同问题的子问题的问题。递归算法通过不断调用自身来解决问题,直到问题被分解为足够简单的问题。
在项目中,递归算法通常用于处理树形结构的数据,例如遍历文件夹、生成目录树等。在使用递归算法时,需要注意以下几点:
- 递归终止条件:递归算法必须有一个终止条件,否则会导致无限递归。
- 递归调用自身:递归算法通过调用自身来实现问题的分解和解决。
- 递归层数:递归算法的层数不能太深,否则会导致栈溢出等问题。
在实际开发中,可以使用递归算法来处理一些复杂的数据结构,例如树形结构、链表等。递归算法的实现通常可以使用函数自身来实现,也可以使用辅助函数来实现。
在我的项目中,我曾经使用递归算法来遍历文件夹,生成文件夹的目录树。具体实现方式是,在遍历文件夹时,先判断当前文件是否为文件夹,如果是,则递归调用自身来处理子文件夹,直到所有文件都被处理完毕。在递归调用自身时,需要传递一些参数,例如当前文件夹的路径、当前层级等,以便于在回调函数中正确地处理数据。
递归算法虽然可以解决一些复杂的问题,但是也存在一些缺点,例如性能问题、栈溢出等问题。因此,在使用递归算法时,需要根据具体的情况进行权衡,选择适合的算法来解决问题。
11、你觉得写自定义hooks时候,你会考虑哪些方面,有没有什么主意的事项
写自定义 hooks 时,我会考虑以下几个方面:
- 复用性:自定义 hooks 应该具有一定的复用性,可以在多个组件中使用,从而避免代码冗余。
- 通用性:自定义 hooks 应该具有一定的通用性,可以适用于多种场景,而不是针对某个具体的功能。
- 可维护性:自定义 hooks 应该具有良好的可维护性,代码结构清晰、命名规范、注释清晰,方便其他开发者理解和维护。
- 灵活性:自定义 hooks 应该具有一定的灵活性,可以根据具体的需求进行定制化开发,同时也需要考虑到未来的扩展性。
- 错误处理:自定义 hooks 应该具有良好的错误处理机制,对于一些错误情况应该有明确的提示和处理方式。
在编写自定义 hooks 时,需要注意以下几个主意事项:
- 命名规范:自定义 hooks 应该以 “use” 开头,以便于其他开发者识别。
- 依赖管理:自定义 hooks 中应该明确列出所有的依赖项,并在 hooks 内部进行判断和处理。
- 副作用管理:自定义 hooks 应该明确列出所有的副作用,并在 hooks 内部进行处理和封装。
- 测试:自定义 hooks 应该进行充分的单元测试,以保证代码的正确性和稳定性。
- 文档:自定义 hooks 应该编写详细的文档,包括使用方法、参数说明、返回值等,以便于其他开发者使用和理解。
在实际开发中,自定义 hooks 可以大大提高代码的复用性和可维护性,同时也可以提高开发效率和代码质量。因此,在编写自定义 hooks 时,需要充分考虑以上方面,并遵循良好的开发规范和代码风格。
12、你在项目中使用vue的时候,做了哪些性能优化
在 Vue 项目中,可以采用以下几种方式进行性能优化:
- 使用 v-if 替代 v-show:v-show 在隐藏元素时只是将元素的 display 样式修改为 none,而不会将元素从 DOM 中删除。因此,如果需要频繁切换元素的显示/隐藏状态,可以使用 v-if 来替代 v-show,从而减少不必要的 DOM 操作。
- 使用 keep-alive 缓存组件:keep-alive 是 Vue 提供的一个内置组件,可以将动态组件缓存起来,在下一次需要使用时直接从缓存中获取,从而避免了组件的重复渲染和销毁。
- 使用异步组件:异步组件可以将组件的加载和渲染放到下一个帧中进行,从而避免了页面卡顿的情况。
- 使用 v-for 的 key:在使用 v-for 渲染列表时,应该为每个元素设置一个唯一的 key,以便于 Vue 进行高效的 DOM 更新。
- 合理使用 computed 和 watch:computed 和 watch 都是用来监听数据变化的,但是它们的实现方式不同。computed 适用于计算复杂的表达式或者依赖于其他属性的数据,而 watch 则适用于监听某个属性的变化,进行相关的操作。
- 使用 Object.freeze 冻结数据:Object.freeze 可以将数据对象冻结,从而避免了数据的修改,提高了数据的稳定性和安全性。
- 使用 SSR 技术:SSR 可以将页面的渲染工作放到服务器端进行,减轻客户端的压力,提高了页面的加载速度和渲染性能。
在我的项目中,我曾经采用以上几种方式进行性能优化,例如使用 v-if 替代 v-show、使用 keep-alive 缓存组件、使用异步组件等。通过这些优化方式,可以显著提高页面的加载速度和渲染性能,提升用户体验。
13、antd 是怎么设计form组件的,为什么要这样子设计(这样子设计个好处、优势)
Ant Design 是基于 React 开发的一套 UI 组件库,其中的 Form 组件是 Ant Design 中的重要组成部分。
Ant Design 的 Form 组件采用了受控组件的设计方式,将表单数据和组件状态绑定在一起。通过 Form.create() 方法可以将表单组件和表单数据进行绑定,从而实现表单数据的收集和验证。
Form 组件还提供了一些常用的表单组件,例如 Input、Radio、Select 等,通过这些组件可以快速地构建复杂的表单。
Ant Design 的 Form 组件设计的优势主要有以下几点:
- 受控组件:采用受控组件的设计方式,可以方便地对表单数据进行控制和管理。
- 易于扩展:Form 组件提供了丰富的 API 和事件,可以方便地对组件进行扩展和定制。
- 良好的用户体验:Form 组件提供了丰富的表单组件和验证规则,可以有效地提高用户体验和数据的安全性。
- 良好的可维护性:Form 组件的代码结构清晰、逻辑清晰,命名规范,文档详细,方便其他开发者理解和维护。
总的来说,Ant Design 的 Form 组件采用了受控组件的设计方式,通过 Form.create() 方法将表单组件和表单数据进行绑定,提供了丰富的表单组件和验证规则,方便了表单的构建和管理,也提高了用户体验和数据的安全性。