大家好,我是若川。我持续组织了近一年的源码共读活动,感兴趣的可以 点此扫码加我微信 lxchuan12 参与,每周大家一起学习200行左右的源码,共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外:目前建有江西|湖南|湖北
籍前端群,可加我微信进群。欢迎星标我的公众号~不错过推文~
今天我们将通过创建一个贷款计算器来学习和实践 ReactJS。这就是我们要创建的项目 👇
这是项目的在线 demo
这是 GitHub 仓库链接
在创建这个项目时,我们将涉及的主题是:
React 功能组件
Material UI
用户输入
处理 Props
Props 解构赋值
useState Hook
还有更多!这个教程对于想通过创建一个真实世界的项目来学习 ReactJs 的初学者来说是非常好的。
项目设置
文件夹结构
Material UI 主题
如何创建导航条
Material UI 网格系统
如何创建 Slider 组件
休息一下
如何使用 useState Hook
如何创建 SliderSelect 组件
如何创建 TenureSelect 组件
如何创建 Result 组件
总结
为了设置该项目,我们需要安装 eact、material-ui 和其他必要的软件包。
首先创建一个名为 mortgage-calculator
的文件夹,在 VS Code 上打开它,然后在终端运行以下命令:
npx create-react-app .
npm install @mui/material @emotion/react @emotion/styled
npm install --save chart.js react-chartjs-2
我们将删除 app.js
中所有的模板代码,保留这部分 👇
import React from "react";function App() {return <div className="App">Hello everyone</div>;
}export default App;
然后在终端运行这个命令来启动服务器:
npm start
该项目现在在 web 浏览器上应该是完全空白的。
开始编程
一切都设置好了,可以开始了。现在,我们将开始构建该项目 :)
文件夹结构
我们的文件夹结构应该是这样的,这样我们就可以轻松地管理和维护文件和文件夹:
mortgage-calculator/
├── src/
│ ├── Components/
│ │ ├── Common/
│ │ │ └── SliderComponent.js
│ │ ├── Navbar.js
│ │ ├── Result.js
│ │ ├── SliderSelect.js
│ │ ├── TenureSelect.js
│ ├── theme.js
│ ├── App.js
│ ├── index.js
├── .gitignore
├── package.json
└── package-lock.json
如果你感到困惑,这里有一张我们的项目文件夹结构的图片:
我们将使用 Material UI 的深色主题。为此,我们需要在 src 文件夹中创建一个名为 theme.js 的文件,并添加以下代码:
import { createTheme } from '@mui/material/styles';export const theme = createTheme({palette: {mode: 'dark',},
})
接下来,我们需要在 index.js
文件中导入 theme,并用 ThemeProvider 来包含应用程序。下面就跟着做吧:👇
import { ThemeProvider } from "@mui/material/styles";
import CssBaseline from "@mui/material/CssBaseline";
import { theme } from "./theme";<React.StrictMode><ThemeProvider theme={theme}><App /><CssBaseline /></ThemeProvider>
</React.StrictMode>
注意:如果你不传递 CssBaseline
组件,我们将无法看到 MUI 的深色主题。
这是目前的结果:👇
整个屏幕将是黑的。这意味着我们的项目已经应用了 Material UI 深色模式。
接下来,我们将创建一个非常简单的导航条来显示 logo。为此,我们需要在 src/Components
文件夹中创建一个名为 Navbar.js
的文件,并添加以下代码:
import AppBar from "@mui/material/AppBar";
import Toolbar from "@mui/material/Toolbar";
import Typography from "@mui/material/Typography";
import { Container } from "@mui/system";const Navbar = () => {return (<AppBar position="static"><Container maxWidth='xl'><Toolbar><Typography variant="h5">Bank of React</Typography></Toolbar></Container></AppBar>);
};export default Navbar;
下面是对 Material UI 中使用的组件的简单解释:
AppBar:Material UI 的 AppBar 组件用于在用户界面上创建一个顶部导航栏。点击这里了解更多。
Container:Material UI 的 Container 组件用于创建一个容器元素,该元素可用于创建一个响应式布局,并在用户界面中集中和包含其他元素。点击这里了解更多。
ToolBar:Toolbar 组件可以包含诸如按钮、文本和图标等元素,也可以用来创建一个适应不同屏幕尺寸的响应式布局。点击这里了解更多。
Typography:Material UI 的 typography 组件用于将预定义的排版样式应用于文本元素。它可以帮助创建一个一致的、视觉上赏心悦目的布局,具有可定制的字体、大小、粗细和间距。点击这里了解更多。
最后,将其导入 App.js,并这样写代码:👇
import React from "react";
import Navbar from "./Components/Navbar";function App() {return (<div className="App"><Navbar /></div>);
}export default App;
这是目前为止的结果:👇
在最终完成的项目中,我们可以看到内容被分成了两部分。左边有滑块组件,右边有饼图。这是用 Material UI 的网格系统实现的。
不仅如此,我们还可以看到,内容在较小的屏幕尺寸上是响应式的。这也是通过使用 Material UI 网格系统实现的。
为了复制这一点,我们需要在 App.js 文件上写上这些东西。你可以在这里跟着做。👇
首先,我们需要从 Material UI 和组件文件夹中导入所有需要的组件:
import React, { useState } from "react";
import { Grid } from "@mui/material";
import { Container } from "@mui/system";
import Navbar from "./Components/Navbar";
import Result from "./Components/Result";
import SliderSelect from "./Components/SliderSelect";
import TenureSelect from "./Components/TenureSelect";
接下来,我们在 return 语句里面写这段代码:👇
<div className="App"><Navbar /><Container maxWidth="xl" sx={{marginTop:4}}><Grid container spacing={5} alignItems="center"><Grid item xs={12} md={6}><SliderSelect /><TenureSelect /></Grid><Grid item xs={12} md={6}><Result/></Grid></Grid></Container>
</div>
对这段代码的解释:
Container:在 Container 上,我们写了 sx={{marginTop:4}}。这是在 Material UI 中为组件添加内联样式的方法。
Grid:Grid 组件被用来创建一个适应不同屏幕尺寸的响应式布局。Grid container 代表父元素,Grid item 代表子元素。
在 Grid 组件上,我们写了 spacing={5}。这是在网格项之间添加间距的方法。
在 Grid 组件上,我们还写了 xs={12},这意味着在超小屏幕上,网格项将占据整个屏幕的宽度。同样地,md={6} 意味着在中等和较大的屏幕上,网格项将占到屏幕的一半。这就是我们如何使组件具有响应性。
这是目前为止的结果:👇
接下来,我们将创建一个滑块组件来获取用户的输入金额。它看起来将是这样的:👇
为此,我们需要在 src/Components/Common 文件夹中创建一个名为 SliderComponent.js 的文件。首先,让我们列出所有需要传递给可重用的滑块组件的 props:
label
min
max
defaultValue
unit
value
steps
amount
onChange
我们开始吧。首先,在 SliderComponent.js
文件中从 MUI 导入以下组件:
import React from "react";
import Slider from "@mui/material/Slider";
import { Typography } from "@mui/material";
import { Stack } from "@mui/system";
我们将使用 MUI 的 Stack 组件来垂直堆叠组件。my
是 marginY
[margin-top & margin-bottom] 的缩写。我们将使用 MUI 的 Typography
组件来显示标签、单位和其他数据。我们将使用 MUI 的 Slider
组件来显示滑块。
先写这一小段代码,解构 props:
const SliderComponent = ({defaultValue,min,max,label,unit,onChange,amount,value,steps
}) => {return (<Stack my={1.4}></Stack>)
}export default SliderComponent
我们将编写这段代码来显示标签、单位和金额。
<Stack gap={1}><Typography variant="subtitle2">{label}</Typography><Typography variant="h5">{unit} {amount}</Typography>
</Stack>
编写这段代码来显示滑块,并像这样把 props 传递给滑块组件:👇
<Slidermin={min}max={max}defaultValue={defaultValue}aria-label="Default"valueLabelDisplay="auto"onChange={onChange}value={value}marksstep={steps}
/>
我们将编写这段代码来显示滑块的最小和最大值。我们将使用 MUI 的 Stack
组件来水平堆叠组件。direction="row"
是 flex-direction: row
的缩写。justifyContent="space-between"
是 justify-content: space-between
的缩写。
<Stack direction="row" justifyContent="space-between"><Typography variant="caption" color="text.secondary">{unit} {min}</Typography><Typography variant="caption" color="text.secondary">{unit} {max}</Typography>
</Stack>
到目前为止,干得不错!
休息一会儿吧——你值得!🎉
我们需要在我们的项目中使用 useState hook。但在此之前,我们需要了解它是什么以及为什么我们需要使用它。
useState hook 是一个内置的 React 函数,允许你向功能组件添加状态。它返回一个包含两个元素的数组
:当前状态值和一个更新该值的函数。useState hook 的一般语法如下:
const [state, setState] = useState(initialState);
其中👇
state:将存储状态的常量或变量的名称
setState:一个更新状态的函数
initialState:状态的初始值
我们将创建一个切换按钮,点击它时,它的文本在 “ON” 和 “OFF” 之间切换。
import React, { useState } from 'react';const ToggleButton = () => {const [isOn, setIsOn] = useState(false);const toggle = () => setIsOn(!isOn)return (<button onClick={toggle}>{isOn ? 'ON' : 'OFF'}</button>);
};export default ToggleButton;
在这里,我们初始化 isOn
状态的初始值为 false
。当用户点击按钮时,toggle
函数将 isOn
状态更新为其相反的值。我们使用一个三元操作符
,根据 isOn
的当前值来渲染按钮内的文本。
现在让我们回到我们的项目中来。首先,在 App.js
文件中,从 React 导入 useState hook。
import React, { useState } from 'react';
接下来,我们将使用 useState hook 声明一个状态来存储滑块的值。我们将在 useState hook 中以 {}
的形式传递状态的初始值,将数据存储为一个对象。
function App() {const [data, setData] = useState({})// other codes are here
}
我们使用 useState hook 来创建一个名为 data
的新状态变量和一个名为 setData
的函数,我们可以用它来更新这个状态。
接下来,我们将把这些值作为默认值传递给滑块组件。
function App() {const [data, setData] = useState({homeValue: 3000,downPayment: 3000 * 0.2,loanAmount: 3000 * 0.8,loanTerm: 5,interestRate: 5,})// other codes are here
}
然后,我们将把 data
和 setData
状态作为一个 prop 传递给 SliderSelect
组件,像这样:👇
<div className="App"><Navbar /><Container maxWidth="xl" sx={{marginTop:4}}><Grid container spacing={5} alignItems="center"><Grid item xs={12} md={6}>{/* this is where we write the code 👇 */}<SliderSelect data={data} setData={setData}/><TenureSelect /></Grid><Grid item xs={12} md={6}><Result/></Grid></Grid></Container>
</div>
所以现在我们已经准备好了可重复使用的 SliderComponent
,将在 SliderSelect.js
组件中使用它。首先,从 Common
文件夹中导入 SliderComponent
组件。
import SliderComponent from "./Common/SliderComponent";
接下来,我们将对从 App.js
收到的 prop 进行解构。同时,创建一个名为 bank_limit
的变量,并给它一个 10000
的值。这代表了一个人可以从我们的银行借到的最大数额的钱。
import React from "react";
import SliderComponent from "./Common/SliderComponent";const SliderSelect = ({ data, setData }) => {const bank_limit = 10000;return (<div></div>);
};export default SliderSelect;
接下来,我们将使用 SliderComponent
来显示名为 Home Value
的滑块。在这里,我们将像这样把 props 传递给 SliderComponent
组件。
const SliderSelect = ({ data, setData }) => {const bank_limit = 10000;return (<div><SliderComponentonChange={(e, value) => {setData({...data,homeValue: Fixed(0),downPayment: (0.2 * value).toFixed(0),loanAmount: (0.8 * value).toFixed(0),});}}defaultValue={data.homeValue}min={1000}max={bank_limit}steps={100}unit="$"amount={data.homeValue}label="Home Value"value={data.homeValue}/></div>);
};
这是目前为止的结果:👇
我们将以同样的方式为 Down Payment
和 Loan Amount
创建滑块,像这样:👇
return (<div>{/* other codes are here */}<SliderComponentonChange={(e, value) =>setData({...data,downPayment: Fixed(0),loanAmount: (data.homeValue - value).toFixed(0),})}defaultValue={data.downPayment}min={0}max={data.homeValue}steps={100}unit="$"amount={data.downPayment}label="Down Payment"value={data.downPayment}/><SliderComponentonChange={(e, value) =>setData({...data,loanAmount: Fixed(0),downPayment: (data.homeValue - value).toFixed(0),})}defaultValue={data.loanAmount}min={0}max={data.homeValue}steps={100}unit="$"amount={data.loanAmount}label="Loan Amount"value={data.loanAmount}/></div>);
这是目前为止的结果:👇
最后,我们将为 Interest Rate 创建滑块。你可以在这里跟着做:👇
return (<div>{/* other codes are here */}<SliderComponentonChange={(e, value) =>setData({...data,interestRate: value,})}defaultValue={data.interestRate}min={2}max={18}steps={0.5}unit="%"amount={data.interestRate}label="Interest Rate"value={data.interestRate}/></div>);
结果如下:👇
接下来,我们将创建 TenureSelect
组件。这个组件将被用来选择贷款的期限。它看起来像这样:👇
首先,像这样把 data
和 setData
状态作为一个 prop 传递给 TenureSelect 组件:👇
return (<div className="App"><Navbar /><Container maxWidth="xl" sx={{marginTop:4}}><Grid container spacing={5} alignItems="center"><Grid item xs={12} md={6}><SliderSelect data={data} setData={setData} />{/* this is where we write the code 👇 */}<TenureSelect data={data} setData={setData}/></Grid><Grid item xs={12} md={6}><Result data={data}/></Grid></Grid></Container></div>
);
然后,从 MUI
库中导入这些所需的组件:
import InputLabel from "@mui/material/InputLabel";
import MenuItem from "@mui/material/MenuItem";
import FormControl from "@mui/material/FormControl";
import Select from "@mui/material/Select";
然后解构我们从 App.js
接收的 props,同时创建一个名为 handleChange
的函数,它将被用来设置 tenure
状态,像这样:👇
const TenureSelect = ({ data, setData }) => {const handleChange = (event) => {setData({...data, loanTerm: event.target.value});};return ()
};export default TenureSelect;
接下来,我们将创建 TenureSelect
组件。它看起来像这样:👇
return (<FormControl fullWidth><InputLabel id="demo-simple-select-label">Tenure</InputLabel><SelectlabelId="demo-simple-select-label"id="demo-simple-select"value={data.loanTerm}label="Tenure"defaultValue={5}onChange={handleChange}><MenuItem value={5}>5 years</MenuItem><MenuItem value={10}>10 years</MenuItem><MenuItem value={15}>15 years</MenuItem><MenuItem value={20}>20 years</MenuItem><MenuItem value={25}>25 years</MenuItem></Select></FormControl>
);
结果如下:👇
最后,我们将创建 Result 组件。这个组件将用于显示每月的贷款分期付款和饼图。它看起来像这样:👇
首先,像这样把 data
状态作为一个 prop 传递给 Result
组件:👇
return (<div className="App"><Navbar /><Container maxWidth="xl" sx={{marginTop:4}}><Grid container spacing={5} alignItems="center"><Grid item xs={12} md={6}><SliderSelect data={data} setData={setData} /><TenureSelect data={data} setData={setData}/></Grid><Grid item xs={12} md={6}>{/* this is where we write the code 👇 */}<Result data={data}/></Grid></Grid></Container></div>
);
接下来,像这样导入所需的组件:👇
import React from "react";
import { Stack, Typography } from "@mui/material";
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js";
import { Pie } from "react-chartjs-2";ister(ArcElement, Tooltip, Legend);
然后像这样解构我们从 App.js
接收的数据状态:👇
const Result = ({ data }) => {const { homeValue, loanAmount, loanTerm, interestRate } = data;return ();
};export default Result;
接下来我们将写出所有帮助我们进行计算的东西:👇
const totalLoanMonths = loanTerm * 12;const interestPerMonth = interestRate / 100 / 12;const monthlyPayment =(loanAmount *interestPerMonth *(1 + interestPerMonth) ** totalLoanMonths) /((1 + interestPerMonth) ** totalLoanMonths - 1);const totalInterestGenerated = monthlyPayment * totalLoanMonths - loanAmount;
然后我们需要这个变量来存储饼图的所有数据,像这样:👇
const pieChartData = {labels: ["Principle", "Interest"],datasets: [{label: "Ratio of Principle and Interest",data: [homeValue, totalInterestGenerated],backgroundColor: ["rgba(255, 99, 132, 0.2)", "rgba(54, 162, 235, 0.2)"],borderColor: ["rgba(255, 99, 132, 1)", "rgba(54, 162, 235, 1)"],borderWidth: 1,},],
};
最后,我们将创建 Result
组件,它是这样的:👇
return (<Stack gap={3}><Typography textAlign="center" variant="h5">Monthly Payment: $ {Fixed(2)}</Typography><Stack direction="row" justifyContent="center"><div><Pie data={pieChartData} /></div></Stack></Stack>
);
结果如下:👇
祝贺你读到最后!现在你可以自信地、有效地使用 ReactJS 和 Material UI 来创建很酷的项目。
你还学会了如何使用 React 的 useState hook,以及如何处理 props。我希望你喜欢这个教程。
作者:Joy Shaheb
译者:Chengjun.L
本文发布于:2024-02-02 22:29:24,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170688416246858.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |