一、期望效果
-
了解js基础语法,并在Demo页内验证
-
在Demo页内实现斐波那契函数,在Chrome控制台输出n=10000的结果
二、实习步骤
2.1 斐波那契数列的定义
斐波那契序列是一个每个数字都是前两个数字之和的序列,通常定义为:

由于直接递归计算斐波那契数列的性能很差(指数级时间复杂度),一般使用动态规划的方式,通过存储已计算的值来避免重复计算,提高效率。这对于计算如n=10000这样大的数非常必要。
2.2 创建基本的React组件结构
在App.jsx添加以下相关组件:
import React, { useState } from 'react';
function App() {
const [n, setN] = useState(''); // 输入的n值
const [result, setResult] = useState(''); // 斐波那契数列计算结果
const handleInputChange = (event) => {
setN(event.target.value); // 更新n的值
};
const calculateFibonacci = () => {
// 斐波那契计算逻辑
};
return (
<div className="App">
<h1>斐波那契数列计算器</h1>
<input
type="number"
value={n}
onChange={handleInputChange}
placeholder="输入一个整数"
/>
<button onClick={calculateFibonacci}>计算</button>
<h2>结果: {result}</h2>
</div>
);
}
export default App;
2.3 添加斐波那契数列计算逻辑
同样是在App.jsx添加一个计算函数:
const calculateFibonacci = () => {
const num = parseInt(n);
if (isNaN(num) || num < 0) {
setResult("请输入一个非负整数");
return;
}
// 处理特殊情况
if (num === 0) {
setResult('0');
return;
} else if (num === 1) {
setResult('1');
return;
}
const fib = [0, 1]; // 基础情况
// 用循环填充fib数组
for (let i = 2; i <= num; i++) {
fib[i] = fib[i - 1] + fib[i - 2];
}
setResult(fib[num].toString()); // 设置计算结果
};
2.4 简单运行一下看看效果
(1)根据界面结果不难发现,界面样式很丑,且结果输出根本不对。

(2)分析失败的原因
在 JavaScript 中,当数字超出 Number.MAX_SAFE_INTEGER(即 2^53−1)或 Number.MAX_VALUE 时,会出问题。在尝试计算 n = 10000 时显示“Infinity”,说明计算结果超出了 JavaScript 可以表示的数值范围。
(3)解决方案
我搜到了以下两种解决方案,暂且先考虑使用方法①来解决上述问题:
①使用大数据库:JavaScript 有一些库,如 big-integer 或 decimal.js,可以处理非常大的数。这些库能够处理超过常规数字限制的数值。
②Web Worker:使用 Web Worker 在后台线程中执行长时间运行的计算,这样可以防止大计算阻塞 UI。
2.5 使用大数据库处理大数据的斐波那契数列
(1)安装 big-integer
npm install big-integer

(2)修改App.js中的计算函数,引入bigInt。
let bigInt;
const loadBigInt = async () => {
if (!bigInt) {
bigInt = (await import('big-integer')).default;
}
};
const calculateFibonacci = async () => {
await loadBigInt(); // 确保 big-integer 已加载
const num = parseInt(n);
if (isNaN(num) || num < 0) {
setResult("请输入一个非负整数");
return;
}
if (num === 0) {
setResult('0');
return;
} else if (num === 1) {
setResult('1');
return;
}
let a = bigInt(0);
let b = bigInt(1);
let sum;
for (let i = 2; i <= num; i++) {
sum = a.add(b);
a = b;
b = sum;
}
setResult(sum.toString()); // 设置计算结果
};
(3)重新运行代码看看效果
能输出了,但是样式很丑,结果很长。

2.6 使用Material-UI库来进行控件的优化
(1)安装Material-UI库
npm install @mui/material @emotion/react @emotion/styled
(2)用Material-UI库来优化空间并用科学计数法来表示结果,以下是修改后的完整的App.js:
import React, { useState } from 'react';
import TextField from '@mui/material/TextField';
import Button from '@mui/material/Button';
import Typography from '@mui/material/Typography';
import Container from '@mui/material/Container';
import Box from '@mui/material/Box';
import bigInt from 'big-integer';
function App() {
const [n, setN] = useState('');
const [result, setResult] = useState('');
const handleInputChange = (event) => {
setN(event.target.value);
};
const formatResult = (num) => {
const str = num.toString();
if (str.length <= 15) return str; // 如果长度小于等于15,直接返回
const base = str.slice(0, 15); // 取前15位
const exponent = str.length - 15; // 指数为长度减去15
return `${base} × 10^${exponent}`;
};
const calculateFibonacci = () => {
const num = parseInt(n);
if (isNaN(num) || num < 0) {
setResult("请输入一个非负整数");
return;
}
if (num === 0) {
setResult('0');
return;
} else if (num === 1) {
setResult('1');
return;
}
let a = bigInt(0);
let b = bigInt(1);
let sum;
for (let i = 2; i <= num; i++) {
sum = a.add(b);
a = b;
b = sum;
}
setResult(formatResult(sum));
};
return (
<Container maxWidth="sm">
<Box sx={{ my: 4, display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
<Typography variant="h4" component="h1" gutterBottom>
斐波那契数列计算器
</Typography>
<TextField
label="输入一个整数"
variant="outlined"
type="number"
value={n}
onChange={handleInputChange}
fullWidth
sx={{ mb: 2 }}
/>
<Button variant="contained" onClick={calculateFibonacci} color="primary">
计算
</Button>
<Typography variant="h6" component="h2" sx={{ mt: 2 }}>
结果: {result}
</Typography>
</Box>
</Container>
);
}
export default App;
(3)运行显示效果
虽然有所改进,但是不居中且美观度不足。

2.7 编写App.css调整页面布局效果
(1)在App.css添加如下代码:
.app-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
text-align: center;
}
(2)App.jsx中需要导入App.css的类,添加如下代码即可:
<Box className="app-container">
/******/
</Box>
(3)运行显示效果
这次看起来要好一些:

2.8 使用particles-bg组件库加一个动态效果的背景
(1)安装库
npm install --save particles-bg
(2)在App.jsx引入该库,并使用let config自定义效果
let config = {
num: [10, 20],
rps: 0.1,
radius: [5, 40],
life: [3, 5],
v: [1, 3],
tha: [-40, 40],
alpha: [0.6, 0],
scale: [1, 0.1],
position: "all",
color: ['random', '#ff0000'],
cross: "dead",
random: 10,
g: 1,
onParticleUpdate: (ctx, particle) => {
ctx.beginPath();
ctx.arc(particle.p.x, particle.p.y, particle.radius, 0, Math.PI * 2);
ctx.fillStyle = particle.color;
ctx.fill();
ctx.closePath();
},
};
(3)在App.jsx中使用该组件
import ParticlesBackground from './ParticlesBackground';
...
<div className="App">
<ParticlesBg type="custom" config={config} bg={true} />
....
</div>
....
(4) 最终效果展示

计算n=10000时的结果

计算n=15时的结果

三、实习总结
根据上述demo的内容可以总结出一些JS的基本语法用法,以一个例子来说明:
1. 函数组件
函数组件是React中定义UI组件的简单方式。这里是本项目中的代码:
function App() {
const [n, setN] = useState('');
const [result, setResult] = useState('');
const handleInputChange = (event) => {
setN(event.target.value);
};
return (
<div className="App">
<TextField
label="输入一个整数"
type="number"
value={n}
onChange={handleInputChange}
/>
<Button onClick={() => setResult(n)}>计算</Button>
<Typography>结果: {result}</Typography>
</div>
);
}
这个组件使用了useState钩子来管理状态,以及通过TextField和Button接收用户输入和触发事件。
2. useState 钩子
useState是一个让函数组件能够使用状态的Hook。以下是本项目中使用它:
const [n, setN] = useState('');
const [result, setResult] = useState('');
这里,n用于存储输入的数字,而result用来存储计算结果。
3. useEffect 钩子
用于在组件渲染到屏幕之后执行副作用操作。例如,如果需要在组件加载后立即执行一个效果(如API调用),可以使用useEffect:
useEffect(() => {
console.log("组件已挂载");
return () => {
console.log("组件将卸载");
};
}, []);
这段代码中,useEffect的回调函数在组件挂载后执行,并且由于依赖列表是空的([]),这个效果只在挂载和卸载时运行。
4. 事件处理
在React中,可以通过简单的事件监听实现交互,如下是一个按钮点击事件的处理:
<Button onClick={calculateFibonacci}>计算</Button>
这里,calculateFibonacci是一个函数,它在点击按钮时被调用,用于执行一些计算逻辑。
5. 第三方库调用
在本项目中,使用了big-integer库来处理大数计算,这展示如何在React项目中调用第三方库的例子:
import bigInt from 'big-integer';
let a = bigInt(0);
let b = bigInt(1);
let sum = a.add(b);
这段代码展示了如何使用big-integer库进行大数加法运算。

被折叠的 条评论
为什么被折叠?



