Skip to content

虚拟列表滚动的时候,会触发很多次重排重绘,怎么优化

  1. 使用 CSS Transform 替代布局属性​​ ​​原理​​:通过 transform: translateY 调整元素位置,利用 GPU 加速(合成层),避免触发重排(Layout)
css
.list-item {
  position: absolute;
  transform: translateY(calc(var(--offset) * var(--item-height)));
  will-change: transform; /* 提示浏览器优化 */
}
.list-item {
  position: absolute;
  transform: translateY(calc(var(--offset) * var(--item-height)));
  will-change: transform; /* 提示浏览器优化 */
}
  1. 节流滚动事件(Throttle)​ 原理​​:限制滚动事件触发频率,避免短时间内多次计算和渲染。 ​​实现​​:
js
let isScrolling = false;
window.addEventListener('scroll', () => {
  if (isScrolling) return;
  isScrolling = true;
  requestAnimationFrame(() => {
    updateVisibleItems(); // 计算可视区域并更新元素
    isScrolling = false;
  });
}, 100); // 每 100ms 最多触发一次
let isScrolling = false;
window.addEventListener('scroll', () => {
  if (isScrolling) return;
  isScrolling = true;
  requestAnimationFrame(() => {
    updateVisibleItems(); // 计算可视区域并更新元素
    isScrolling = false;
  });
}, 100); // 每 100ms 最多触发一次
  1. 预加载与缓冲区(Buffer)​ ​原理​​:在可视区域上下预加载少量元素,避免滚动时出现空白(白屏)或频繁触发新渲染。 ​​实现​​:
js
const buffer = 5; // 预加载前后各 5 条数据
const startIndex = Math.max(0, Math.floor(scrollTop / itemHeight) - buffer);
const endIndex = Math.min(totalCount, startIndex + visibleCount + buffer * 2);
const buffer = 5; // 预加载前后各 5 条数据
const startIndex = Math.max(0, Math.floor(scrollTop / itemHeight) - buffer);
const endIndex = Math.min(totalCount, startIndex + visibleCount + buffer * 2);
  1. 使用 requestAnimationFrame 优化渲染​​ ​​原理​​:将渲染逻辑合并到浏览器下一次重绘前执行,减少重复渲染。 ​​实现​​:
js
let pendingScrollUpdate = null;
window.addEventListener('scroll', () => {
  if (pendingScrollUpdate) return;
  pendingScrollUpdate = requestAnimationFrame(() => {
    updateVisibleItems();
    pendingScrollUpdate = null;
  });
});
let pendingScrollUpdate = null;
window.addEventListener('scroll', () => {
  if (pendingScrollUpdate) return;
  pendingScrollUpdate = requestAnimationFrame(() => {
    updateVisibleItems();
    pendingScrollUpdate = null;
  });
});
  1. 启用硬件加速​​ ​​原理​​:通过 CSS 属性触发 GPU 加速,减少主线程负担。 ​​优化点​​:
css
.virtual-list {
  transform: translateZ(0); /* 强制 GPU 加速 */
}
.list-item {
  backface-visibility: hidden; /* 防止动画闪烁 */
}
.virtual-list {
  transform: translateZ(0); /* 强制 GPU 加速 */
}
.list-item {
  backface-visibility: hidden; /* 防止动画闪烁 */
}

大文件上传,单个文件去hash

WebSocket和SSE

TCP三次握手

web Worker返回大数据量的时候怎么优化

优化方向具体措施性能提升效果
数据传输使用 Transferable Objects减少内存复制开销
数据量分块/流式传输避免主线程阻塞
序列化采用二进制格式(如 MessagePack)减少序列化时间
并行处理多 Worker + 数据分片提升计算并发度
内存管理及时释放引用防止内存泄漏

react事件和浏览器事件有什么区别(冒泡和捕获流程)

react17和react18的区别

  1. Concurrent Mode(并行模式)
  • React 17: 引入了 Concurrent Mode 的概念,这是一个实验性功能,旨在提高应用的响应速度和渲染效率。它允许多个任务同时进行,从而减少主线程的阻塞。
  • React 18: 将 Concurrent Mode 转为默认行为,并进行了多项改进,包括更好的内存管理和性能优化。开发者可以更轻松地利用并行渲染来提升用户体验。
  1. Performance Improvements(性能改进)
  • React 17: 提供了一些初步的性能优化,特别是在组件渲染和状态更新方面。
  • React 18: 进一步提升了性能,尤其是在处理大型应用时。React 18 引入了新的垃圾回收机制和更高效的渲染流程。
  1. Server Components(服务器组件)
  • React 17: 引入了对服务器组件的支持,允许开发者在服务端渲染部分组件,从而减少客户端的负担。
  • React 18: 进一步优化了服务器组件的支持,并增加了对自动卸载未使用的组件的功能。
  1. Error Boundaries(错误边界)
  • React 17: 改进了错误边界的处理机制,使得在出现错误时能够更优雅地恢复组件。
  • React 18: 继续优化错误边界,增加了对自定义错误边界的更多控制和更好的调试支持。
  1. New Features and Improvements(新功能和改进)
  • React 17:
    • 引入了 createRoot API,用于替代旧的 ReactDOM.render 方法。
    • 改进了对 Context API 的支持。
  • React 18:
    • 提供了更好的 TypeScript 支持。
    • 增加了对 Web Workers 的初步支持,允许在后台线程中运行 JavaScript,从而提升性能。
  1. Backwards Compatibility(向后兼容性)
  • React 17: 向后兼容性良好,大部分代码可以直接从 React 16 升级到 React 17。
  • React 18: 同样保持了良好的向后兼容性,但需要注意一些弃用的 API 和特性。

react hook用过哪些

useState、useEffect、useMemo、useCallback、useContext

跨端兼容性问题解决过哪些

说一下this指向

说一下事件循环

做一道事件循环的题目

js
console.log('script start')
async function fun1(){
  await fun2()
  console.log('async1')
}
async function fun2(){
  console.log('async2')
}
fun1()
setTimeout(()=>{
  console.log('setTimeout')
},0)
new Promise((resolve)=>{
  console.log('promise1')
  resolve()
}).then(()=>{
  console.log('promise2')
}).then(()=>{
  console.log('promise3')
})
console.log('script end')
console.log('script start')
async function fun1(){
  await fun2()
  console.log('async1')
}
async function fun2(){
  console.log('async2')
}
fun1()
setTimeout(()=>{
  console.log('setTimeout')
},0)
new Promise((resolve)=>{
  console.log('promise1')
  resolve()
}).then(()=>{
  console.log('promise2')
}).then(()=>{
  console.log('promise3')
})
console.log('script end')

script start async2 promise1 script end async1 promise2 promise3 setTimeout

说一下输出

js
var number = 5;

var foo = {
  number: 3,
  fn: (function () {
    var number; // 块级作用域变量
    this.number *= 2; // 修改全局number → 5 * 2=10
    number = 3; // 局部变量赋值
    return function () {
      const num = number; // 获取闭包中的number(3)
      console.log(num); // 第一次输出3
      number *= 3; // 闭包number变为9
      console.log(number); // 第二次输出9
    };
  })(),
};

const fn2 = foo.fn;
fn2.call(null); // 调用1 → 输出3,9
foo.fn(); // 调用2 → 输出9,27
console.log(window.number); // 最终输出10
var number = 5;

var foo = {
  number: 3,
  fn: (function () {
    var number; // 块级作用域变量
    this.number *= 2; // 修改全局number → 5 * 2=10
    number = 3; // 局部变量赋值
    return function () {
      const num = number; // 获取闭包中的number(3)
      console.log(num); // 第一次输出3
      number *= 3; // 闭包number变为9
      console.log(number); // 第二次输出9
    };
  })(),
};

const fn2 = foo.fn;
fn2.call(null); // 调用1 → 输出3,9
foo.fn(); // 调用2 → 输出9,27
console.log(window.number); // 最终输出10

括号的深度

输入:"(()(()))"

输出:3

js
var maxDepth = function (s) {
    let ans = 0, size = 0;
    for (let i = 0; i < s.length; ++i) {
        const ch = s[i];
        if (ch === '(') {
            ++size;
            ans = Math.max(ans, size);
        } else if (ch === ')') {
            --size;
        }
    }
    return ans;
};
var maxDepth = function (s) {
    let ans = 0, size = 0;
    for (let i = 0; i < s.length; ++i) {
        const ch = s[i];
        if (ch === '(') {
            ++size;
            ans = Math.max(ans, size);
        } else if (ch === ')') {
            --size;
        }
    }
    return ans;
};

Released under the MIT License.