1、js事件循环
-
调用栈(Call Stack):
- JavaScript 是单线程的,所有的代码执行都是在调用栈中进行的。
- 当函数被调用时,进入栈中;执行完毕后,从栈中弹出。
-
任务队列(Task Queue):
- 当异步操作完成(如网络请求、定时器等)时,回调函数会被放入任务队列中。
- 这些函数会在调用栈空闲时被执行。
-
事件循环(Event Loop):
- 事件循环是一个持续运行的循环,它监测调用栈和任务队列。
- 当调用栈为空时,事件循环会将任务队列中的第一个任务移入调用栈执行。
下面是一个简单的示例,展示了事件循环的工作原理:
console.log('Start');
setTimeout(() => {
console.log('Timeout 1');
}, 0);
setTimeout(() => {
console.log('Timeout 2');
}, 0);
Promise.resolve().then(() => {
console.log('Promise 1');
});
Promise.resolve().then(() => {
console.log('Promise 2');
});
console.log('End');
// 在全局代码执行完后,事件循环会首先处理微任务队列中的 Promise 回调,然后再处理任务队列中的 setTimeout 回调。
Start
End
Promise 1
Promise 2
Timeout 1
Timeout 2
2、
// 理解它的执行顺序以及输出结果
setTimeout(function() {
console.log(1);
});
new Promise(function(resolve, reject) {
console.log(2);
resolve(3);
}).then(function(val) {
console.log(val);
});
2
3
1
(function test() {
setTimeout(function() {
console.log(4);
}, 0);
new Promise(function executor(resolve) {
console.log(1);
for (var i = 0; i < 10000; i++) {
i == 9999 && resolve();
}
console.log(2);
}).then(function() {
console.log(5);
});
console.log(3);
})();
console.log('script end');
1
2
3
script end
5
4
3、背景:在前端开发中,展示超长列表数据时,如果直接渲染会导致性能问题。为了解决这一问题,需要使用虚拟列表技术。
要求:使用React 实现一个虚拟列表组件。 该组件需要支持以下功能:
自定义列表项的高度。
动态加载数据(模拟异步加载)。
滚动到任意位置时,能正确渲染可视区域内的列表项。
提供简单的示例代码展示组件的用法。
import React, { useState, useEffect, useRef } from 'react';
const VirtualList = ({ itemHeight, itemCount }) => {
const [data, setData] = useState([]);
const [scrollTop, setScrollTop] = useState(0);
const listRef = useRef(null);
// 模拟异步加载数据
useEffect(() => {
const loadData = () => {
const newData = Array.from({ length: itemCount }, (_, index) => `Item ${index + 1}`);
setData(newData);
};
loadData();
}, [itemCount]);
const handleScroll = (e) => {
setScrollTop(e.target.scrollTop);
};
const startIndex = Math.floor(scrollTop / itemHeight);
const endIndex = Math.min(startIndex + Math.ceil(listRef.current.clientHeight / itemHeight), itemCount);
const visibleItems = data.slice(startIndex, endIndex);
return (
<div
ref={listRef}
onScroll={handleScroll}
style={{
height: '400px',
overflowY: 'auto',
position: 'relative',
}}
>
<div style={{ height: `${itemCount * itemHeight}px`, position: 'relative' }}>
{visibleItems.map((item, index) => (
<div
key={index}
style={{
height: `${itemHeight}px`,
position: 'absolute',
top: `${(startIndex + index) * itemHeight}px`,
lineHeight: `${itemHeight}px`,
border: '1px solid #ccc',
boxSizing: 'border-box',
padding: '0 10px',
}}
>
{item}
</div>
))}
</div>
</div>
);
};
// 示例用法
const App = () => {
return (
<div>
<h1>Virtual List Example</h1>
<VirtualList itemHeight={30} itemCount={1000} />
</div>
);
};
export default App;
// VirtualList 组件:
接受 itemHeight(每个列表项的高度)和 itemCount(列表项总数)作为 props。
使用 useState 来管理列表数据和滚动位置。
使用 useEffect 模拟异步加载数据。
事件处理:
handleScroll 函数用于更新滚动位置。
计算可视区域内的列表项,并通过 slice 方法获取可见的列表项。
渲染:
计算 startIndex 和 endIndex,根据滚动位置渲染相应的列表项。
使用绝对定位来渲染列表项,以确保它们在正确的位置。