<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>React App</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="root"></div>
<script type="module" src="./main.tsx"></script>
</body>
</html>
index.html
style.css
tsx
main.tsx
tsx
app.tsx
package.json
现在支持上传本地图片了!
index.html
style.css
body {
padding: 0;
margin: 0;
background-color: #fefefe;
text-align: center;
}
.main {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
}
h1 {
font-family: Inter, sans-serif;
}
i {
color: #777;
}
.div-container {
display: flex;
flex-direction: column;
}
.div-item {
width: 100%;
height: 500px;
color: white;
text-align: center;
line-height: 50px;
}
.loading {
text-align: center;
margin-top: 20px;
}
编辑器加载中
main.tsx
import { createRoot } from "react-dom/client"
import App from "./app.tsx"
const root = createRoot(document.getElementById("root"))
root.render(<App />)
console.log(["Hello 笔.COOL 控制台"])
编辑器加载中
app.tsx
import { useState, useEffect } from "react";
const App = () => {
const [list, setList] = useState<Array<{ background: string }>>([
{ background: "rgb(233,32,38)" }
]);
const [loading, setLoading] = useState(false);
const [count, setCount] = useState(0);
// 模拟后端数据返回
const getList = (num: number): Promise<Array<{ background: string }>> => {
return new Promise((resolve) => {
setTimeout(() => {
const newList = Array.from({ length: num }, () => ({
background: `rgb(${Math.floor(Math.random() * 256)},${Math.floor(
Math.random() * 256
)},${Math.floor(Math.random() * 256)})`
}));
resolve(newList);
}, Math.random() * 5000);
});
};
//模拟请求
const fetchData = async () => {
if (count >= 50 || loading) return;//超过50条不再发起 且如果之前的请求还未完成就不发起下一个
setLoading(true);
const newList = await getList(10);
setList((prevList) => [...prevList, ...newList]);//处理返回的数据
setCount((prevCount) => prevCount + 10);
setLoading(false);
};
//第一次渲染触发 请求 只触发一次
useEffect(() => {
fetchData();
}, []);
// 监听count,loading
useEffect(() => {
const handleScroll = () => {
// 滚动超过一半且列表长度小于50触发 且没有上一个请求 请求
if (
window.innerHeight + window.scrollY >= document.body.scrollHeight / 2 &&
count < 50&&
!loading
) {
fetchData();
}
};
window.addEventListener("scroll", handleScroll);//监听滚动事件
//移除之前添加的滚动事件监听器,防止内存泄漏和多次事件处理
return () => window.removeEventListener("scroll", handleScroll);
}, [count,loading]);
return (
<div className="div-container">
{list.map((item, index) => (
<div
key={index}
className="div-item"
style={{ backgroundColor: item.background }}
>
{index}
</div>
))}
{loading && <div className="loading">Loading...</div>}
</div>
);
};
export default App;
编辑器加载中
package.json
注意:新添加的依赖包首次加载可能会报错,稍后再次刷新即可
{
"dependencies": {
"react": "18.3.1",
"react-dom": "18.3.1",
"canvas-confetti": "1.9.3"
}
}
编辑器加载中
预览页面