MIT实习前置培训笔记2---JS基础(在React Demo的基础上实现斐波那契数列)

一、期望效果

  1. 了解js基础语法,并在Demo页内验证

  2. 在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-integerdecimal.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钩子来管理状态,以及通过TextFieldButton接收用户输入和触发事件。

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库进行大数加法运算。

   

  • 9
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值