使用json-server模拟React的数据源
开发人员在构建React.js项目时需要一些带有端点的快速使用的数据源。这些数据源提供了测试数据,以测试软件包是否正常工作。
数据源是数据诞生的初始位置。它可能是一个数据库、平面文件、来自物理设备的实时测量数据,等等。
数据源主要被用作数据库管理系统管理的数据库,如MySQL、Postgres、SQL等。这种方法的问题是,在原型开发过程中,如果应用程序的原型不符合预期,它将很快被抛弃。
快速原型开发方法是一种敏捷的系统开发方法,它允许人们创建一个原型来测试和验证需求规格文件(RSD)的要求。
这种开发是通过几次迭代进行的。原型可以作为主要系统使用,也可以被抛弃,这样就可以在原型的基础上开发另一个主要系统。通过建立一个原型,可以避免额外的设置和配置,如果它们很快被丢弃。
这个过程产生了一个需求,即创建一个可以快速设置和丢弃的数据源,但它可以执行与DBMS相同的功能。它还应该足够小,有较少的存储需求,以产生预期的正确和准确的结果。
json-server
库可以解决这样的数据源问题。json-server
库在React应用中可以快速安装、配置、使用和废弃。在这篇文章中,你将学习如何在React.js应用程序中对上述包进行以下操作。
主要收获
到最后,读者将学到以下内容。
- 什么是
json-server
库? - 在React.js应用程序中设置
json-server
库。 - 将应用程序连接到库中。
- 将该库作为数据源,代替实际的DBMS。
- 从应用程序中移除依赖关系并丢弃原型。
先决条件
需要以下条件。
- 在机器上设置好的IDE或文本编辑器。
- 一个稳定的互联网连接。
- 已经设置好的React开发环境。
- React开发技能。
关于文章中要做的事情的简要信息如下。
- 学习关于JSON服务器包的简介。
- 创建一个React.js应用程序。
- 将其设置为允许来自链接的API数据。
- 对应用程序进行样式设计。
- 在机器上安装JSON服务器。
- 将JSON服务器设置为一个模拟数据库服务器。
- 在项目中配置JSON服务器的数据源。
- 运行应用程序。
了解json-server包
JSON服务器允许几乎所有类型的后端请求和响应,如GET
,POST
,PUT
,PATCH
, 和DELETE
方法。它有访问存储在模拟数据库文件(JSON)中的数据项的路由。
几个例子是:GET /posts
,获取所有的帖子,PUT /posts/1
,更新第一个帖子,或者DELETE /posts/1
,删除第一个帖子。该模块允许对数据库进行其他操作,例如。
进行数据库过滤
例如 -GET /posts?title=json-server&author=riro
或GET/comments?author.name=riro
。这些端点分别用json-server
的title
和author
的名称riro
和comments
的author
的名称riro
来过滤posts
。
为获取的结果添加分页功能
例子 -GET /posts?_page=9&_limit=23
.这个请求将从9
页面获取帖子,并且页面限制被设置为23
。
对数据库中的项目进行排序
例子 -GET/posts/5/comments?_sort=votes,likes&_order=desc,asc
.这个请求根据votes
和likes
分别以升序和降序的方式对comments
进行排序。
对数据进行分片操作
例子 -GET/posts/4/comments?_start=20&_limit=10
.这个请求从评论号20
开始,截断comments
后的评论10
。
操作员
当排除一个值时,我们使用_ne
,而要基于一个值进行过滤,我们使用_like
。一个例子GET /posts/4/comments?_ne=sad
请求,排除了任何值为sad
的评论,而GET \author_like=chris
搜索与chris
相关的名称的authors
(使用 RegEx)。
在数据库中进行全文搜索
例子 -GET/posts?q=tomcat
.这个请求在所有存储的记录中搜索值tomcat
。
与数据库中的项目建立关系
使用_embed
包含子资源,使用_expand
包含父资源,可以创建嵌套资源。一个例子是GET /comments/1?_expand=post
,它包括了名称为post
的父资源。
获取完整的数据库
例子 -GET\db
。这个GET
,获取了指定数据库的所有数据库项目。
构建React.js应用程序
在本节中,将创建一个React.js应用程序。我们将建立一个预算规划的应用程序,从列表中添加或删除它们。该应用程序使用JSON对象从数据源保存和检索数据。
让我们开始吧。打开应该创建应用程序的文件夹,运行这个命令。
npx create-react-app react-budget-tracker
文件夹结构应该是这样的。
.
├── node_modules
├── public
├── src
│ └── components
│ ├── About.js
│ ├── AddBudget.js
│ ├── Budget.js
│ ├── Budgets.js
│ ├── Button.js
│ ├── Footer.js
│ └── Header.js
│ ├── App.js
│ ├── index.css
│ ├── index.js
│ └── reportWebVitals.js
├── .eslintcache
├── .gitignore
├── db.json
├── package.json
├── package-lock.json
├── README.md
└── yarn.lock
头部组件
顾名思义,Header.js
文件包含头部分。
- 在
Header.js
,其代码如下所示。
import PropTypes from 'prop-types'
import { useLocation } from 'react-router-dom'
import Button from './Button'
const Header = ({ title, onAdd, showAdd }) => {
const location = useLocation()
/*The header has a title and a button that opens up a window to add the budget or close the window*/
return (
<header className='header'>
<!-- The header has a title -->
<h1>{title}</h1>
{location.pathname === '/' && (
<Button
color={showAdd ? 'red' : 'green'}
text={showAdd ? 'Close' : 'Add'}
onClick={onAdd}
/>
)}
</header>
)
}
/*Set the title*/
Header.defaultProps = {
title: 'Budget Tracker',
}
Header.propTypes = {
title: PropTypes.string.isRequired,
}
/*Export the header*/
export default Header
这段代码为网页创建了一个简单的页眉,并允许它用于添加以下内容。
- 一个页眉标题。
- 一个添加预算项目和删除预算项目的按钮。
- 设置按钮的颜色。
- 设置标题值并导出页眉。
页脚组件
- 在
Footer.js
文件中,以下将是代码。
import { Link } from 'react-router-dom'
/*Add a footer to the application*/
const Footer = () => {
return (
/*It has a copyright and a link to the about page*/
<footer>
<p>Copyright © 2021</p>
<Link to='/about'>About</Link>
</footer>
)
}
export default Footer
该代码会生成一个包含版权和关于页面链接的页脚。
按钮组件
Button.js
增加了一个可重复使用的按钮组件,用于多个点击动作。例如,这个按钮可以打开Add
表格和Close
表格。
import PropTypes from 'prop-types'
/*A button that allows one to set its color, the text it displays and the function it executes on a click event*/
const Button = ({ color, text, onClick }) => {
return (
<button
onClick={onClick}
style={{ backgroundColor: color }}
className='btn'
>
{text}
</button>
)
}
Button.defaultProps = {
color: 'steelblue',
}
Button.propTypes = {
text: PropTypes.string,
color: PropTypes.string,
onClick: PropTypes.func,
}
export default Button
该代码生成了一个按钮,允许人们设置其。
- 颜色。
- 文本,以及
- 当它被点击时要执行的功能。
关于网页组件
- 现在,添加一个关于网页,包含与作者有关的细节。
import { Link } from 'react-router-dom'
/*Generates a simple about page that has a simple button to go back to the main page*/
const About = () => {
return (
<div>
<h4>Version 1.0.0</h4>
<Link to='/'>
<button type="button" className={"btn btn-secondary"}>
Go Back
</button>
</Link>
</div>
)
}
export default About
预算.js文件
Budget.js
文件使人们能够与显示在屏幕上的服务器中的特定预算项目互动。人们可以删除一个预算或切换其提醒状态。
import { FaTimes } from 'react-icons/fa'
/*This will enable one to set the reminder to the budget on or off when double clicked on; and also to delete the budget*/
const Budget = ({ budget, onDelete, onToggle }) => {
return (
<!-- Toggle the budget reminder on or off when double on double click -->
<div
className={`budget ${budget.reminder && 'reminder'}`}
onDoubleClick={() => onToggle(budget.id)}
>
<h3>
<!-- Display the budget name -->
{budget.name}{' '}
<FaTimes
/*Delete the budget when clicked*/
style={{ color: 'red', cursor: 'pointer' }}
onClick={() => onDelete(budget.id)}
/>
</h3>
<!-- Display the budget Amount -->
<p>{budget.amount}</p>
</div>
)
}
export default Budget
上面的代码。
- 当双击时,充当提醒状态的切换器(开、关)。
- 显示项目和金额。
AddBudget组件
AddBudget.js
文件允许人们向系统添加预算。然后,预算将立即在系统中被更新,并使其可见。
import { useState } from 'react'
const AddBudget = ({ onAdd }) => {
const [name, setName] = useState('')
const [amount, setAmount] = useState('')
const [reminder, setReminder] = useState(false)
const onSubmit = (e) => {
e.preventDefault()
/*Ensure that the name input is never null*/
if (!name) {
alert('Please add a budget')
return
}
/*When adding the budget, store the name, amount and the reminder status*/
onAdd({ name: name, amount: amount, reminder })
setName('')
setAmount('')
setReminder(false)
}
/*Display a form that allows one to enter the budget values*/
return (
<form className='add-form' onSubmit={onSubmit}>
<div className='form-control'>
<label>Budget</label>
<input
type='text'
placeholder='Add Budget'
value={name}
onChange={(e) => setName(e.target.value)}
/>
</div>
<!-- Take in the amount -->
<div className='form-control'>
<label>Amount</label>
<input
type='text'
placeholder='Amount'
value={amount}
onChange={(e) => setAmount(e.target.value)}
/>
</div>
<!-- Take in the reminder status -->
<div className='form-control form-control-check'>
<label>Set Reminder</label>
<input
type='checkbox'
checked={reminder}
value={reminder}
onChange={(e) => setReminder(e.currentTarget.checked)}
/>
</div>
<input type='submit' value='Save Budget' className='btn btn-block' />
</form>
)
}
export default AddBudget
上面的代码。
- 在添加过程中,如果没有添加预算项目,会显示一个错误。
- 否则,它会将输入的数值添加到数据源中的其他数值中。当提交按钮被按下时,添加就发生了。
- 它允许人们为某一项目设置提醒
on
或off
。 - 然后,应用程序将自动重新加载添加的列表。
Budgets.js文件
- 在
Budgets.js
文件中,我们可以添加以下代码。
import Budget from './Budget'
/*Displays all the budgets fetched from the URL to the screen*/
const Budgets = ({ budgets, onDelete, onToggle }) => {
/*Maps each budget per the budget's key*/
return (
<>
{budgets.map((budget, index) => (
<Budget key={index} budget={budget} onDelete={onDelete} onToggle={onToggle} />
))}
</>
)
}
export default Budgets
这段代码。
- 显示预算列表中的项目。
- 允许从列表中,以及从数据源中删除这些项目。
- 它允许人们使用一个切换函数来设置提醒
on
或off
。
从服务器上获取项目
这一步是在App.js
文件中完成的。它规定了应用程序如何与服务器交互,以及如何处理获取的数据。
/*Import the other components for the application*/
import {useEffect, useState} from 'react'
import {BrowserRouter as Router, Route} from 'react-router-dom'
import Header from './components/Header'
import Footer from './components/Footer'
import Budgets from './components/Budgets'
import AddBudget from './components/AddBudget'
import About from './components/About'
const App = () => {
const [showAddBudget, setShowAddBudget] = useState(false)
const [budgets, setBudgets] = useState([])
useEffect(() => {
/*Make the app fetch the items assynchronously*/
const getBudgets = async () => {
const budgetsFromServer = await fetchBudgets()
setBudgets(budgetsFromServer)
}
getBudgets()
}, [])
该代码导入了所需的模块,并允许从服务器上异步获取数据项。
- 在前面的代码下添加下面的代码。
// Fetch Budgets
const fetchBudgets = async () => {
const res = await fetch('http://localhost:5000/budgets')
const data = await res.json()
return data
}
// Fetch Budgets
const fetchBudget = async (id) => {
const res = await fetch(`http://localhost:5000/budgets/${id}`)
const data = await res.json()
return data
}
// Add Budget
const addBudget = async (budget) => {
const res = await fetch('http://localhost:5000/budgets', {
method: 'POST',
headers: {
'Content-type': 'application/json',
},
body: JSON.stringify(budget),
})
const data = await res.json()
setBudgets([...budgets, data])
}
// Delete Budget
const deleteBudget = async (id) => {
const res = await fetch(`http://localhost:5000/budgets/${id}`, {
method: 'DELETE',
})
//We should control the response status to decide if we will change the state or not.
res.status === 200
? setBudgets(budgets.filter((budget) => budget.id !== id))
: alert('Error Deleting This Budget')
}
// Toggle Reminder
const toggleReminder = async (id) => {
const budgetToToggle = await fetchBudget(id)
const updateBudget = {...budgetToToggle, reminder: !budgetToToggle.reminder}
const res = await fetch(`http://localhost:5000/budgets/${id}`, {
method: 'PUT',
headers: {
'Content-type': 'application/json',
},
body: JSON.stringify(updateBudget),
})
const data = await res.json()
setBudgets(
budgets.map((budget) =>
budget.id === id ? {...budget, reminder: data.reminder} : budget
)
)
}
该代码指定了其中的URL,可以。
-
添加一个新的预算。
-
删除一个预算。
-
获取预算。
-
切换提醒状态。
-
现在添加一个返回和一个导出语句,如下所示。
/*Display all the budgets fetched, otherwise display that there are no budgets to show*/
return (
<Router>
<div className='container'>
<Header
onAdd={() => setShowAddBudget(!showAddBudget)}
showAdd={showAddBudget}
/>
<Route
path='/'
exact
render={(props) => (
<>
{showAddBudget && <AddBudget onAdd={addBudget}/>}
{budgets.length > 0 ? (
<Budgets
budgets={budgets}
onDelete={deleteBudget}
onToggle={toggleReminder}
/>
) : (
'No Budgets To Show'
)}
</>
)}
/>
<Route path='/about' component={About}/>
<Footer/>
</div>
</Router>
)
}
export default App
上面显示的这段代码做了以下工作。
- 从指定的URL中获取项目并显示它们。
- 将项目添加到列表中。
- 删除数据源中的项目。
- 切换项目提醒(开,关)状态。
- 如果应用程序在服务器上没有找到数据,它将显示没有找到预算;否则,它将显示所有其他预算。
- 该代码还包含页脚和关于页面的链接。
应用程序的风格
- 现在我们可以为应用程序创建样式。样式代码可以在这个链接上找到。下载它并保存在
src
文件夹中。
在使用下面的命令运行应用程序之前,请确保运行下面的命令来安装所有必要的软件包。
npm install
使用下面的命令运行创建的应用程序。
npm run start
该应用程序将如下图所示。
安装json-server
JSON服务器可以通过运行下面的命令来安装。
npm install -g json-server
该命令在全局范围内安装该软件包。安装完毕后,前往package.json
文件,添加一个快速运行服务器的脚本。
"server": "json-server --watch db.json --port 5000"
上面这段代码运行一个服务器,为应用程序的请求提供响应。在这个应用程序中充当数据库的数据源是db.json
文件。如上图所示,它将通过端口5000
,并在App.js
文件中被访问。
配置json-server数据源
在db.json
文件中,服务器在http://localhost:5000/budgets/
URL下提供请求。数据项在预算部分下。
把下面的代码复制粘贴到db.json
文件中。
{
"budgets": [
{
"id": 1,
"name": "Carrots",
"amount": "1500",
"reminder": false
},
{
"id": 2,
"name": "Laundry",
"amount": "2500",
"reminder": true
},
{
"id": 3,
"name": "Ginger",
"amount": "1000",
"reminder": true
},
{
"id": 4,
"name": "Electricity",
"amount": "10000",
"reminder": true
},
{
"name": "Water",
"amount": "13000",
"reminder": true,
"id": 5
}
]
}
它包含预算部分下的五个项目。这些是Carrots
,Laundry
,Ginger
,Electricity
, 和Water
。
运行应用程序
通过以下方式测试JSON服务器。
- 在一个终端中通过使用运行主React应用程序。
npm run start
- 在另一个终端中,使用运行服务器。
npm run server
- 在浏览器中通过以下URL访问该应用程序。
http://localhost:3000/
. - 重新加载应用程序的浏览器窗口,直到它显示项目,如果它因任何原因不工作。
结果应该像下面的例子一样。
关于JSON服务器的更多信息
让我们更多地了解这个包。
改变端口、文件和文件路径
通过在终端运行下面的命令,可以将服务器运行的文件名和端口改为database.json
,端口为3010
。
json-server --watch database.json --port 3010
- 位于不同文件夹中的静态文件也可以提供服务,如下图所示。
json-server database.json --static ./public/database
对数据进行查询
在使用搜索栏进行搜索时,这一操作可能会有帮助。按照下面的步骤进行。
- 通过在一个新的终端上运行以下内容来查询数据库中的一个特定值。
curl http://localhost:5000/budgets?q=Carrots
在这里,数据库中被搜索到任何一个数值为Carrots
的项目。返回值看起来像下面的例子。
该模块允许中间件、随机数据生成、远程访问数据源、设置自定义路由等。
添加延迟和改变主机
- 要改变主机,使用
-H
或--host
选项。 - 给服务器添加一些延迟(以毫秒为单位),以复制一个真实的服务器,使用
-d
或--delay
选项。
这两个选项都显示在下面。
json-server --watch db.json --port 5000 -H 127.0.0.1 -d 1500
结论
总之,在软件开发过程中,运行和丢弃的部分对开发者来说是必不可少的。这些部件对敏捷编程和原型设计很有帮助。JSON服务器依赖性是一个可快速丢弃的项目开发单元的例子。
它体积小,易于安装、使用、学习,并在人们使用完原型后进行处置。
在这一点上,已经涵盖了以下内容。
- 什么是JSON服务器模块。
- JSON服务器模块在项目开发阶段的重要性。
- 将JSON服务器模块添加到React项目中。
- 配置JSON服务器模块。