如何实现高性能Tree组件
实现Tree组件的核心思路是什么?
Tree组件的核心思路是将原始的嵌套children数据结构平铺成一维数组,然后通过计算每个节点的深度(deep)、层级关系等信息,在渲染时动态计算缩进宽度、连接线等,从而实现树形结构的可视化。
Tree组件如何实现高性能大数据渲染?
- 将原始树形数据平铺为一维数组,便于后续计算
- 计算出实际需要渲染的节点数据,过滤隐藏的节点
- 利用虚拟列表技术只渲染可视区域的数据,实现大数据量的高效渲染
function flattenTreeData(treeData = [], parent = null) { const nodes = []; treeData.forEach((node) => { const newNode = { ...node, parent, }; nodes.push(newNode); if (newNode.children) { nodes.push(...flattenTreeData(newNode.children, newNode)); } }); return nodes; }
如何计算Tree组件中节点的各种状态(展开/折叠、选中等)?
- 展开/折叠状态根据ExpandedKeys计算
- 复选框选中状态需要考虑受控/非受控,严格受控模式,及父子节点关联
- 需要递归计算父节点和子节点的状态
- 利用平铺后的索引进行相关节点查询
function flattenTreeData(treeData = [], parent = null) { const nodes = []; treeData.forEach((node) => { const newNode = { ...node, parent, }; nodes.push(newNode); if (newNode.children) { nodes.push(...flattenTreeData(newNode.children, newNode)); } }); return nodes; }
Tree组件的交互如何实现?点击节点展开折叠,复选框状态切换等
- 点击展开折叠通过更新节点自身状态、可视状态及ExpandedKeys实现
- 点击复选框需要递归更新父子节点的状态,及相关keys
- 计算并保存实时状态,通过回调函数通知外部
function toggleExpanded(nodes, node) { return nodes.map((currentNode) => { if (currentNode === node) { return { ...currentNode, expanded: !currentNode.expanded, }; } return currentNode; }); } // 在渲染时计算缩进: function renderNode(node) { const indentLevel = getIndentLevel(node); const style = { paddingLeft: `${indentLevel * 16}px`, }; return ( <div style={style} onClick={() => handleNodeClick(node)}> {node.label} </div> ); }
如何实现高性能表格Table组件?
可参考ali-react-table:高性能 React 表格组件
表格组件的性能瓶颈主要在哪里?
- 渲染大量 DOM;
- 频繁的更新渲染,如选中行状态改变引起整个表格重新渲染。
如何优化表格组件的渲染性能?
- 只渲染必要的列:
const columnsToRender = columns.filter(column => column.shouldRender); return ( <table> <thead> <tr> {columnsToRender.map(column => ( <th key={column.key}>{column.title}</th> ))} </tr> </thead> <tbody> {data.map(row => ( <tr key={row.id}> {columnsToRender.map(column => ( <td key={column.key}>{row[column.key]}</td> ))} </tr> ))} </tbody> </table> );
- 细粒度更新,只更新变化行/列。在React中,可以使用
React.memo
或者shouldComponentUpdate
来避免不必要的重渲染:
function Row({ data, columns }) { return ( <tr> {columns.map(column => ( <Cell key={column.key} data={data[column.key]} /> ))} </tr> ); } const areEqual = (prevProps, nextProps) => { return prevProps.data === nextProps.data && prevProps.columns === nextProps.columns; }; export default React.memo(Row, areEqual);
- 采用虚拟化技术,只渲染可视区的行。可以使用第三方库如
react-window
或者react-virtualized
来实现:
import { FixedSizeList as List } from "react-window"; function Table({ data, columns }) { const Row = ({ index, style }) => ( <div style={style}> {columns.map(column => ( <Cell key={column.key} data={data[index][column.key]} /> ))} </div> ); return ( <List height={500} itemCount={data.length} itemSize={35} > {Row} </List> ); }
使用Web Workers来处理数据处理或计算密集型任务:
// 创建一个新的 worker const worker = new Worker('worker.js'); // 向 worker 发送数据 worker.postMessage(data); // 监听 worker 的消息 worker.addEventListener('message', (event) => { // 更新表格数据 updateTable(event.data); });
在worker.js
中:
self.addEventListener('message', (event) => { // 处理数据 const processedData = processData(event.data); // 发送处理后的数据 self.postMessage(processedData); });
基于Web Components封装组件库
这个可以当做拓展了解一下,目前有越来越多的开源组件库往这个方向发展,可以参考这篇文章如何基于 WebComponents 封装 UI 组件库
图解算法小册
微前端
组件库
axios
nginx
docekr
git
nodejs
- 面试官:说说 Node 文件查找的优先级以及 Require 方法的文件查找策略?
- 面试官:说说对 Node 中的 process 的理解?有哪些常用方法?
- 面试官:Node性能如何进行监控以及优化?
- 面试官:如果让你来设计一个分页功能, 你会怎么设计? 前后端如何交互?
- 面试官:说说你对Node.js 的理解?优缺点?应用场景?
- 面试官:说说对中间件概念的理解,如何封装 node 中间件?
- 面试官:如何实现jwt鉴权机制?说说你的思路
- 面试官:说说 Node. js 有哪些全局对象?
- 面试官:说说对 Node 中的 fs模块的理解? 有哪些常用方法
- 面试官:如何实现文件上传?说说你的思路
- 面试官:说说对Nodejs中的事件循环机制理解?
- 面试官:说说对 Node 中的 Stream 的理解?应用场景?
- 面试官:说说Node中的EventEmitter? 如何实现一个EventEmitter?
- 面试官:说说对 Node 中的 Buffer 的理解?应用场景?
HTTP
- 面试官:说说HTTP 常见的状态码有哪些,适用场景?
- 面试官:说说 HTTP 常见的请求头有哪些? 作用?
- 面试官:说说TCP为什么需要三次握手和四次挥手?
- 面试官:说说地址栏输入 URL 敲下回车后发生了什么?
- 面试官:说说对WebSocket的理解?应用场景?
- 面试官:如何理解UDP 和 TCP? 区别? 应用场景?
- 面试官:如何理解TCP/IP协议?
- 面试官:如何理解OSI七层模型?
- 面试官:什么是HTTP? HTTP 和 HTTPS 的区别?
- 面试官:为什么说HTTPS比HTTP安全? HTTPS是如何保证安全的?
- 面试官:说一下 GET 和 POST 的区别?
- 面试官:DNS协议 是什么?说说DNS 完整的查询过程?
- 面试官:如何理解CDN?说说实现原理?
- 面试官:说说 HTTP1.0/1.1/2.0 的区别?
webpack
- 面试官:说说你对webpack的理解?解决了什么问题?
- 面试官:说说webpack proxy工作原理?为什么能解决跨域?
- 面试官:说说如何借助webpack来优化前端性能?
- 面试官:如何提高webpack的构建速度?
- 面试官:说说webpack的构建流程?
- 面试官:与webpack类似的工具还有哪些?区别?
- 面试官:说说webpack中常见的Plugin?解决了什么问题?
- 面试官:说说Loader和Plugin的区别?编写Loader,Plugin的思路?
- 面试官:说说webpack中常见的Loader?解决了什么问题?
- 面试官:说说webpack的热更新是如何做到的?原理是什么?
react
- 面试官:super() 和 super(props) 有什么区别?
- 面试官:说说你在使用React 过程中遇到的常见问题?如何解决?
- 面试官:state 和 props 有什么区别?
- 面试官:说说 React中的setState执行机制
- 面试官:说说React服务端渲染怎么做?原理是什么?
- 面试官:说说React render方法的原理?在什么时候会被触发?
- 面试官:说说你对Redux的理解?其工作原理?
- 面试官:说说 React 生命周期有哪些不同阶段?每个阶段对应的方法是?
- 面试官:React中的key有什么作用?
- 面试官:说说你是如何提高组件的渲染效率的?在React中如何避免不必要的render?
- 面试官:说说react中引入css的方式有哪几种?区别?
- 面试官:说说你对immutable的理解?如何应用在react项目中?
- 面试官:你在React项目中是如何使用Redux的? 项目结构是如何划分的?
- 面试官:说说React diff的原理是什么?
- 面试官:说说对受控组件和非受控组件的理解?应用场景?
- 面试官:React中组件之间如何通信?
- 面试官:说说对React中类组件和函数组件的理解?有什么区别?
- 面试官:说说你在React项目是如何捕获错误的?
- 面试官:在react中组件间过渡动画如何实现?
- 面试官:说说React的事件机制?
- 面试官:说说对Redux中间件的理解?常用的中间件有哪些?实现原理?
- 面试官:说说 Real DOM 和 Virtual DOM 的区别?优缺点?
- 面试官:说说对 React 的理解?有哪些特性?
- 面试官:说说对React refs 的理解?应用场景?
- 面试官:说说你对React Router的理解?常用的Router组件有哪些?
- 面试官:说说React Router有几种模式?实现原理?
- 面试官:说说对React Hooks的理解?解决了什么问题?
- 面试官:说说React JSX转换成真实DOM过程?
- 面试官:说说 React 性能优化的手段有哪些?
- 面试官:说说对高阶组件的理解?应用场景?
- 面试官:说说对Fiber架构的理解?解决了什么问题?
- 面试官:React构建组件的方式有哪些?区别?
- 面试官:React事件绑定的方式有哪些?区别?
vue3
- 面试官:说说Vue 3.0中Treeshaking特性?举例说明一下?
- 面试官:Vue3.0里为什么要用 Proxy API 替代 defineProperty API ?
- 面试官:Vue3.0性能提升主要是通过哪几方面体现的?
- 面试官:用Vue3.0 写过组件吗?如果想实现一个 Modal你会怎么设计?
- 面试官:Vue3.0的设计目标是什么?做了哪些优化
- 面试官:Vue3.0 所采用的 Composition Api 与 Vue2.x 使用的 Options Api 有什么不同?
vue
- 面试官:vue3有了解过吗?能说说跟vue2的区别吗?
- 面试官:有使用过vue吗?说说你对vue的理解
- 面试官:什么是虚拟DOM?如何实现一个虚拟DOM?说说你的思路
- 面试官:说下你的vue项目的目录结构,如果是大型项目你该怎么划分结构和划分组件呢?
- 面试官:SSR解决了什么问题?有做过SSR吗?你是怎么做的?
- 面试官:你对SPA单页面的理解,它的优缺点分别是什么?如何实现SPA应用呢
- 面试官:说说你对slot的理解?slot使用场景有哪些?
- 面试官:v-show和v-if有什么区别?使用场景分别是什么?
- 面试官:vue要做权限管理该怎么做?如果控制到按钮级别的权限怎么做?
- 面试官:Vue.observable你有了解过吗?说说看
- 面试官:Vue中的$nextTick有什么作用?
- 面试官:Vue实例挂载的过程
- 面试官:Vue常用的修饰符有哪些有什么应用场景
- 面试官:说说你对vue的mixin的理解,有什么应用场景?
- 面试官:请描述下你对vue生命周期的理解?在created和mounted这两个生命周期中请求数据有什么区别呢?
- 面试官:你知道vue中key的原理吗?说说你对它的理解
- 面试官:说说你对keep-alive的理解是什么?
- 面试官:v-if和v-for的优先级是什么?
- 面试官:SPA首屏加载速度慢的怎么解决?
- 面试官:Vue中的过滤器了解吗?过滤器的应用场景有哪些?
- 面试官:你是怎么处理vue项目中的错误的?
- 面试官:你有写过自定义指令吗?自定义指令的应用场景有哪些?
- 面试官:你了解vue的diff算法吗?说说看
- 面试官:动态给vue的data添加一个新的属性时会发生什么?怎样解决?
- 面试官:为什么data属性是一个函数而不是一个对象?
- 面试官:Vue项目中你是如何解决跨域的呢?
- 面试官:Vue中组件和插件有什么区别?
- 面试官:Vue组件之间的通信方式都有哪些?
- 面试官:双向数据绑定是什么
- 面试官:你了解axios的原理吗?有看过它的源码吗?
- 面试官:Vue项目中有封装过axios吗?主要是封装哪方面的?
- 面试官:vue项目本地开发完成后部署到服务器后报404是什么原因呢?
TypeScript
- 面试官:说说你对TypeScript的认识?
- 面试官:TS实战之扑克牌排序
- 面试官:类型
- 面试官:枚举和泛型
- 面试官:接口和类
- 面试官:命名空间和模块
- 面试官:函数
- 面试官:高级类型
- 面试官:解读TSConfig
- 面试官:装饰器与反射元数据
- 面试官:类型兼容:结构化类型
- 面试官:类型系统层级
- 面试官:类型推断
- 面试官:类型守卫
- 面试官:泛型和类型体操
- 面试官:扩展类型定义
- 面试官:类型兼容:协变和逆变
JavaScript
- 面试官:requestAnimationFrame:优化动画和渲染的利器
- 面试官:Javascript数据类型和类型转换
- 面试官:JavaScript事件流:深入理解事件处理和传播机制
- 面试官:执行上下文与闭包
- 面试官:JavaScript数组
- 面试官:JavaScript对象
- 面试官:函数上下文和this关键字
- 面试官:作用域和作用域链
- 面试官:JavaScript中的编码
- 面试官:原型和原型链
- 面试官:异步的终极解决方案:async/await
- 面试官:实现符合Promise/A+规范的Promise
- 面试官:JS中的异步编程与Promise
- 面试官:JavaScript中的Generator函数与其在实现Async/Await的应用
- 面试官:前端跨页面通信:实现页面间的数据传递与交互
- 面试官:面向对象编程与Class
- 面试官:详解Cookie, Session, SessionStorage, LocalStorage
- 面试官:JavaScript修饰器:简化代码,增强功能
- 面试官:深入理解Proxy
- 面试官:Date类:日期和时间处理
Linux
CSS
- 面试官:css选择器有哪些?优先级?哪些属性可以继承?
- 面试官:如果要做优化,CSS提高性能的方法有哪些?
- 面试官:元素水平垂直居中的方法有哪些?如果元素不定宽高呢?
- 面试官:如何实现单行/多行文本溢出的省略样式?
- 面试官:CSS如何画一个三角形?原理是什么?
- 面试官:介绍一下grid网格布局
- 面试官:说说flexbox(弹性盒布局模型)
- 面试官:深入理解设备像素、CSS像素、设备独立像素、DPR、PPI之间的区别与适配方案
- 面试官:说说你对盒子模型的理解?
- 面试官:谈谈你对BFC的理解?
CSS3
小程序
- 面试官:说说微信小程序的实现原理?
- 面试官:说说微信小程序的支付流程?
- 面试官:说说提高微信小程序的应用速度的手段有哪些?
- 面试官:说说微信小程序中路由跳转的方式有哪些?区别?
- 面试官:说说微信小程序的登录流程?
- 面试官:说说微信小程序的生命周期函数有哪些?
- 面试官:说说你对微信小程序的理解?优缺点?