1.一个页面从输入URL到页面加载显示完成发生了什么? DNS解析 浏览器渲染:解析HTML生成DOM树,解析CSS生成CSSOM树,将DOM树和CSSOM树合并成渲染树 根据生成的渲染树来进行回流和重绘 将像素发送给GPU,显示在页面上
2.http三次握手
3.http和https的区别 http:超文本传输协议,是一个基于请求与响应,无状态的,应用层的协议, 常基于TCP/IP协议传输数据, 互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准 https:HTTPS是身披SSL外壳的HTTP,是以安全为目标的HTTP通道, 是HTTP的安全版,利用SSL/TLS建立全信道,加密数据包, 提供对网站服务器的身份认证,同时保护交换数据的隐私和完整性。 区别:HTTPS协议需要到CA申请证书,一般免费的证书很少,需要交费; HTTP协议运行在TCP之上,所有传输的内容都是明文;HTTPS运行在SSL/TLS之上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的; HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443; HTTPSke可以有效的防止运营商劫持,解决了防劫持的一个大问题。
4.什么是重绘和重排(回流): 重绘:当某些元素的外观改变,但不影响它在文档流中的位置时,触发重绘。 浏览器会重新绘制受影响元素的外观,但不会改变它们的布局。 重排:当页面布局发生变化,影响了元素的位置和尺寸时,触发重排。 会导致整个渲染树的重新计算,涉及布局和几何属性的更新。
5.React高效的原因 创建虚拟DOM树:这是真实DOM的JavaScript对象表示 当组件的状态或属性发生改变时,React会重新渲染组件生成新的虚拟DOM树,然后通过高效算法(Diff算法)比较新旧差异 只更新虚拟DOM树中发生变化的部分到真实DOM树中,而不是重新渲染整个DOM树,从而减少了不必要的重绘和重排操作,提高了性能。 Diff算法:递归比较新旧DOM树的节点,计算出最小化的更新操作,只更新变化的部分到真实DOM树中。 异步更新:React采用异步更新机制,将多个状态更新合并成一个更新操作,从而减少了不必要的重绘和重排操作,提高了性能。
6.react中函数组件和class组件的区别: 函数组件: 没有实例,没有生命周期方法,没有状态管理 函数组件是无状态的,没有实例,没有生命周期方法,没有状态管理 函数组件通过hooks来实现状态管理
7.节流和防抖 节流: 函数在n秒内只执行一次,如果多次触发,忽略执行 function throttle(fn, wait) { let startTime = Date.now()
return function () { const nowTime = Date.now()
if (nowTime - startTime >= wait) {
startTime = nowTime
return fn.apply(this, arguments)
}
} } 防抖: 在连续触发的事件中,只有在最后一次事件发生后的一定时间间隔内没有新的事件触发时,才执行相应的处理函数 function debounce(fn, wait, immediate = false) { let timer = null
return function () { // 存在定时器 清空 if (timer) { clearInterval(timer) timer = null } // 立即执行 if (immediate) { // 判断是否执行过 如果执行过 timer 不为空 const flag = !timer
// 执行函数
flag && fn.apply(this, arguments)
// n 秒后清空定时器
timer = setTimeout(() => {
timer = null
}, wait)
} else {
timer = setTimeout(() => {
fn.apply(this, arguments)
}, wait)
}
} } 8.图片懒加载 延迟加载,只加载当前屏幕的图片,可视区域外的图片不会进行加载,只有当屏幕滚动的时候才加载。 将图片地址存储到 data-xxx 属性上 判断图片是否在可视区域 如果在,就设置图片 src 绑定 scroll 监听事件
腾讯PCG内容平台一面凉经
先是自我介绍,然后讲一下项目,问了青训营是什么
然后问react相关的技术问题
1.react用的是什么版本
19.0
2.经常使用的react hooks
①useState 在函数组件中声明和更新状态变量
初始化状态
setState更新状态
②useEffect 在组件渲染后执行副作用操作
在组件加载、更新或卸载时执行副作用操作。
类似于类组件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount
useEffect(() => {
const fetchUser = async () => {
const response = await fetch(https://api.example.com/users/${userId});
const data = await response.json();
setUser(data);
};
fetchUser();
}, [userId]); // 依赖数组,只有 userId 变化时才会重新执行
问用的是class组件还是函数式组件 我说错了,应该说函数式组件的 ③useContext 用于在组件树中共享数据 ④useRef 用于创建可变的引用对象 ⑤useMemo 和 useCallback 用于优化性能,避免不必要的重新计算和函数创建
3.react的state改变之后,dom是怎么变化的 首先是状态更新的触发,调用 setState 或 useState 的更新函数 重新渲染组件,生成新的虚拟 DOM React 使用高效的算法(如 Diff 算法)比较新旧虚拟 DOM 树的差异 Diff 算法会递归比较新旧虚拟 DOM 树的节点,找出哪些节点发生了变化,包括: 节点的添加:新虚拟 DOM 中有而旧虚拟 DOM 中没有的节点。 节点的删除:旧虚拟 DOM 中有而新虚拟 DOM 中没有的节点。 节点的更新:新旧虚拟 DOM 中都有的节点,但属性或内容发生了变化。 节点的移动:新旧虚拟 DOM 中的节点顺序发生了变化。 Diff 算法会生成一个最小化的更新操作列表 React 会将这些最小化的更新操作批量应用到真实 DOM 上。这个过程称为提交(Commit)。React 会尽量减少对真实 DOM 的操作次数,以提高性能
4.说一下react的vnode结构 虚拟 DOM 的每个节点称为 VNode VNode 包含以下属性: tag:节点的标签名,如 'div'、'span' 等。 props:节点的属性对象,包含节点的属性和事件处理函数。 children:节点的子节点,可以是字符串、数字、数组或 VNode 对象。 key:用于标识节点的唯一性,用于优化 Diff 算法的性能。 当 React 的 render 方法被调用时,它会根据组件的状态和属性生成一个新的 VNode React 中的 VNode 有多种类型,每种类型对应不同的节点: -原生 DOM 节点:如 div、span 等。 -函数组件节点:表示由函数组件返回的 VNode。 -类组件节点:表示由类组件返回的 VNode。 -文本节点:表示文本内容。 -Fragment 节点:用于包裹多个子节点,但不生成额外的 DOM 元素
5.jsx是怎么转换成js的 JSX(JavaScript XML)是一种看起来像 HTML 的语法,并不是真正的 HTML,而是 JavaScript 的一种扩展语法。 JSX 代码需要被转换为纯 JavaScript 代码,才能在浏览器中运行。这个转换过程通常由工具(如 Babel)完成,将 JSX 代码转换为 React.createElement 调用。
6.js中的事件循环 js是单线程语言,但是可以通过异步任务来实现多线程的效果,处理异步操作,协调事件处理 工作原理: 执行栈:(调用栈) 存储函数调用关系的数据结构 函数调用时压入执行栈,执行完毕从栈顶弹出 任务队列: 包括宏任务队列和微任务队列 存储异步任务的队列 异步任务完成时,将其添加到任务队列中 循环机制: 事件循环不断检查执行栈和任务队列 宏任务和微任务 宏任务: 包括: 整体代码script setTimeout setInterval setImmediate(Node.js) I/O操作(如文件读写、网络请求等) UI渲染 微任务: 包括: Promise.then MutationObserver process.nextTick(Node.js) queueMicrotask(浏览器) 微任务的执行时机: 在当前宏任务执行完毕后立即执行 微任务队列中的微任务按照添加顺序执行
7.垂直居中能说出来几种方法
8.git 的使用 怎么提交代码到远程仓库: -初始化 Git 仓库(如果尚未初始化):git init -配置用户信息(如果尚未配置):git config -添加文件到暂存区:git add -提交到本地仓库:git commit -关联远程仓库(如果尚未关联):git remote add -推送到远程仓库:git push
9.tcp和udp的区别 tcp和udp都是传输层协议 区别有: ①连接的建立 TCP是面向连接的协议,在数据传输开始之前,必须先建立连接。 TCP通过三次握手过程来建立连接,确保两端的通信是同步的。 UDP是面向数据报的协议,发送数据之前不需要建立连接,直接将数据包发送给接收方,不保证数据包的顺序、完整性或可靠性。 ②数据传输的可靠性 TCP通过序列号、确认应答、重传机制、流量控制和拥塞控制等技术来确保数据完整无误地传输到接收方 UDP则不保证数据传输的可靠性。它发送的数据包可能会丢失、重复或到达顺序错乱,不提供错误恢复功能 ③数据传输的速度和效率 TCP的传输速度相对较慢,因为它需要进行连接建立和数据传输的过程。 UDP的传输速度相对较快,因为不需要建立连接,且几乎没有错误恢复机制 ④流量控制和拥塞控制 TCP具有流量控制和拥塞控制机制,可以根据网络条件调整数据传输速率,避免网络拥堵。 UDP发送方的发送速率不会根据网络条件进行调整 ⑤使用场景 TCP适用于需要高可靠性的应用,如网页浏览、电子邮件、文件传输等 UDP适用于对传输速度和效率要求高、可以容忍一定数据丢失的应用,如在线视频会议、实时游戏、流媒体等 10.前端跨域
11.http的请求方法有哪几种
12.react的生命周期 怎么控制不更新
13.markdown怎么生成url
14.react的router有哪几种模式
快手一面凉经
1.响应迅速是有什么指标吗 2.markdown的语法格式是怎么解析的 为什么选择正则表达式 还知道其他方式吗 3.题目 setTimeout(() => { console.log(1); }, 0);
console.log(2);
new Promise((resolve) => { console.log(3); resolve(); }).then(() => { console.log(4); });
console.log(5); 给出输出的顺序 答案:2 3 5 1 4? 了解过宏任务微任务吗 4.隐藏页面元素的方式 ①display:none 隐藏对应元素使其不可见 不占据页面的空间,用户无法看到或进行交互 ②visibility:hidden 仍占据页面上的空间,只是视觉上不可见 ③透明度 opacity:0 取值范围0-1 0完全透明 1完全不透明 设置为0时不可见 占用页面空间 用户可以交互 ④position 给定四个方向上任意一个较大的值或负值,能将元素设置到屏幕之外,不可见 position:absolute 脱离当前文档流 position:relative 只是将元素移出 在当前位置仍占据一定空间 ⑤clip-path
⑥hidden属性 ⑦width:0 ⑧font-size:0
5.常见的http状态码 2xx 成功状态码 请求正常处理完毕 3xx 重定向状态码 需要进行附加操作以完成请求 4xx 客户端错误状态码 服务器无法处理请求 5xx 服务器错误状态码 服务器处理请求出错
200 OK:请求成功 204:请求成功,未返回内容 用于删除数据 206:对资源某一部分的请求 301:永久性重定向 302:临时重定向 400:请求报文中存在语法错误,服务器无法理解 401:'无访问权限,用户名、密码、令牌错误' 403:'得到访问授权,但访问是被禁止', 404:访问的资源不存在 405: '请求方式不正确', 406: '请求的数据格式不是服务接收的类型' 500:服务器内部错误 503:服务器过载或维护,暂时无法处理请求 6.排序算法 ①冒泡排序 function bubbleSort(arr) { const n = arr.length; for (let i = 0; i < n - 1; i++) { for (let j = 0; j < n - i - 1; j++) { if (arr[j] > arr[j + 1]) { [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; } } } return arr; } ②选择排序 每次从待排序序列中选择最小(大)的元素,放到已排序序列的末尾 function selectionSort(arr) { const n = arr.length; for (let i = 0; i < n - 1; i++) { let minIndex = i; for (let j = i + 1; j < n; j++) { if (arr[j] < arr[minIndex]) { minIndex = j; } } [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]; } return arr; } ③插入排序 function insertionSort(arr) { const n = arr.length; for (let i = 1; i < n; i++) { let key = arr[i]; let j = i - 1; while (j >= 0 && arr[j] > key) { arr[j + 1] = arr[j]; j--; } arr[j + 1] = key; } return arr; } ④快速排序 选择一个基准值,将数组分为两部分,一部分小于基准值,一部分大于基准值,然后递归地对两部分进行排序 function quickSort(arr) { if (arr.length <= 1) { return arr; } const pivot = arr[0]; const left = []; const right = []; for (let i = 1; i < arr.length; i++) { if (arr[i] <= pivot) { left.push(arr[i]); } else { right.push(arr[i]); } } return [...quickSort(left), pivot, ...quickSort(right)]; } ⑤归并排序 function mergeSort(arr) { if (arr.length <= 1) { return arr; } const mid = Math.floor(arr.length / 2); const left = mergeSort(arr.slice(0, mid)); const right = mergeSort(arr.slice(mid)); return merge(left, right); }
function merge(left, right) { let result = []; let i = 0; let j = 0; while (i < left.length && j < right.length) { if (left[i] < right[j]) { result.push(left[i++]); } else { result.push(right[j++]); } } return [...result, ...left.slice(i), ...right.slice(j)]; }