React开发:数据存储API与URL路由的应用
1. 使用数据存储API
在开发过程中,我们常常需要使用数据存储API来管理组件与数据存储之间的连接。下面将详细介绍相关的操作和概念。
1.1 添加属性到组件
在
SupplierDisplay.js
文件中,我们可以添加属性来控制组件的渲染。以下是示例代码:
export const SupplierDisplay = connectFunction(
class extends Component {
render() {
if (this.props.editing) {
return <ConnectedEditor key={ this.props.selected.id || -1 } />
} else {
return <div className="m-2">
<ConnectedTable needSuppliers={ true } />
<div className="text-center">
<button className="btn btn-primary m-1"
onClick={ this.props.createSupplier }>
Create Supplier
</button>
</div>
</div>
}
}
})
从代码中可以看出,根据
this.props.editing
的值,组件会渲染不同的内容。当
editing
为
true
时,渲染
ConnectedEditor
组件;否则,渲染包含
ConnectedTable
和创建供应商按钮的内容。
1.2 过早优化的风险
在开发过程中,不要过早地进行优化。因为几乎所有的优化都会增加项目的复杂性,而且未优化代码带来的性能损失可能并不明显。更好的做法是先编写清晰、简单的代码,然后再对不符合要求的部分进行优化。
1.3 映射函数属性
connect
函数的第二个参数用于映射函数属性,它可以是一个对象或一个函数。
-
对象形式
:当提供一个对象时,对象的每个属性值都被假定为一个动作创建函数,并会自动包装在
dispatch
方法中,映射到一个函数属性。
-
函数形式
:当提供一个函数时,该函数会接收
dispatch
方法,并负责使用它来创建函数属性映射。同时,还可以选择接收连接器组件的属性。
以下是使用函数配置函数属性的示例代码:
import { connect } from "react-redux";
import { startEditingProduct, startEditingSupplier } from "./stateActions";
import { deleteProduct, deleteSupplier } from "./modelActionCreators";
import { PRODUCTS, SUPPLIERS } from "./dataTypes";
export const TableConnector = (dataType, presentationComponent) => {
const mapStateToProps = (storeData, ownProps) => {
if (!ownProps.needSuppliers) {
return { products: storeData.modelData[PRODUCTS] };
} else {
return {
suppliers: storeData.modelData[SUPPLIERS].map(supp => ({
...supp,
products: supp.products.map(id =>
storeData.modelData[PRODUCTS]
.find(p => p.id === Number(id)) || id)
.map(val => val.name || val)
}))
}
}
}
const mapDispatchToProps = (dispatch, ownProps) => {
if (!ownProps.needSuppliers) {
return {
editCallback: (...args) => dispatch(startEditingProduct(...args)),
deleteCallback: (...args) => dispatch(deleteProduct(...args))
}
} else {
return {
editCallback: (...args) => dispatch(startEditingSupplier(...args)),
deleteCallback: (...args) => dispatch(deleteSupplier(...args))
}
}
}
return connect(mapStateToProps, mapDispatchToProps)(presentationComponent);
}
在上述代码中,
mapStateToProps
函数根据
ownProps.needSuppliers
的值返回不同的数据属性;
mapDispatchToProps
函数根据同样的条件返回不同的函数属性。
1.4 合并属性
connect
函数接受第三个参数
mergeProps
,它是一个函数,用于在将属性传递给展示组件之前组合这些属性。该函数接收映射的数据属性、函数属性和连接组件的属性,并返回一个合并后的对象。
以下是合并属性的示例代码:
import { connect } from "react-redux";
import { endEditing } from "./stateActions";
import { PRODUCTS, SUPPLIERS } from "./dataTypes";
import { saveAndEndEditing } from "./multiActionCreators";
export const EditorConnector = (dataType, presentationComponent) => {
const mapStateToProps = (storeData) => ({
editing: storeData.stateData.editing
&& storeData.stateData.selectedType === dataType,
product: (storeData.modelData[PRODUCTS]
.find(p => p.id === storeData.stateData.selectedId)) || {},
supplier:(storeData.modelData[SUPPLIERS]
.find(s => s.id === storeData.stateData.selectedId)) || {}
})
const mapDispatchToProps = {
cancelCallback: endEditing,
saveCallback: (data) => saveAndEndEditing(data, dataType)
}
const mergeProps = (dataProps, functionProps, ownProps) =>
({ ...dataProps, ...functionProps, ...ownProps })
return connect(mapStateToProps, mapDispatchToProps,
mergeProps)(presentationComponent);
}
在这个示例中,
mergeProps
函数将数据属性、函数属性和连接组件的属性合并在一起。
1.5 设置连接选项
connect
方法的最后一个参数通常命名为
options
,它是一个对象,用于配置与数据存储的连接。以下是
options
对象的属性说明:
| 属性名 | 描述 |
| ---- | ---- |
| pure | 默认情况下,连接器组件只有在自身属性或从数据存储中选择的值发生变化时才会更新。将此属性设置为
false
表示连接器组件可能依赖于其他数据,高阶组件不会尝试阻止更新。默认值为
true
。 |
| areStatePropsEqual | 当
pure
属性为
true
时,此函数用于覆盖
mapStateToProps
值的默认相等性比较,以最小化更新。 |
| areOwnPropsEqual | 当
pure
属性为
true
时,此函数用于覆盖
mapDispatchToProps
值的默认相等性比较,以最小化更新。 |
| areMergedPropsEqual | 当
pure
属性为
true
时,此函数用于覆盖
mergeProps
值的默认相等性比较,以最小化更新。 |
| areStatesEqual | 当
pure
属性为
true
时,此函数用于覆盖整个组件状态的默认相等性比较,以最小化更新。 |
2. 使用URL路由
在开发复杂应用时,URL路由可以使项目结构更清晰,便于扩展和维护。下面将介绍URL路由的相关概念和使用方法。
2.1 URL路由概述
URL路由是指使用浏览器的当前URL来选择要展示给用户的内容。与传统的通过按钮事件处理程序调度Redux动作的方式不同,URL路由通过渲染锚元素来导航到新的URL,并根据这些URL选择和展示相应的内容。
URL路由的优点包括:
- 无需共享状态数据,状态数据编码在URL中,便于更改应用结构。
- 使项目结构更清晰,易于扩展和维护。
但也需要注意,需要进行全面的测试,以确保用户可以导航的所有URL都能正确处理并显示适当的内容。
2.2 准备工作
在使用URL路由之前,需要进行一些准备工作。首先,安装
react-router-dom
包:
npm install react-router-dom@4.3.1
然后,简化
App
组件的内容,示例代码如下:
import React, { Component } from "react";
import { Provider } from "react-redux";
import dataStore from "./store";
import { Selector } from "./Selector";
import { ProductDisplay } from "./ProductDisplay";
import { SupplierDisplay } from "./SupplierDisplay";
export default class App extends Component {
render() {
return <Provider store={ dataStore }>
<Selector>
<ProductDisplay name="Products" />
<SupplierDisplay name="Suppliers" />
</Selector>
</Provider>
}
}
最后,启动React开发工具:
npm start
2.3 开始使用URL路由
在
Selector
组件中使用URL路由,示例代码如下:
import React, { Component } from "react";
import { BrowserRouter as Router, Link, Route } from "react-router-dom";
import { ProductDisplay } from "./ProductDisplay";
import { SupplierDisplay } from "./SupplierDisplay";
export class Selector extends Component {
render() {
return <Router>
<div className="container-fluid">
<div className="row">
<div className="col-2">
<div><Link to="/products">Products</Link></div>
<div><Link to="/suppliers">Suppliers</Link></div>
</div>
<div className="col">
<Route path="/products" component={ ProductDisplay } />
<Route path="/suppliers" component={ SupplierDisplay} />
</div>
</div>
</div>
</Router>
}
}
在这个示例中,使用了三个组件来设置基本的路由配置:
-
Router
:提供对URL路由功能的访问,通常使用
BrowserRouter
并将其命名为
Router
,作为需要访问路由功能的内容的容器。
-
Link
:渲染一个用户可以点击的元素,用于导航到新的URL。通过
to
属性指定导航URL。
-
Route
:等待浏览器导航到特定的URL,并在匹配时显示相应的组件。
2.4 响应导航
Route
组件用于实现应用的路由方案,通过等待浏览器导航到特定的URL并显示相应的组件。
Route
组件的属性可以配置URL匹配和内容选择,以下是
Route
组件的属性说明:
| 属性名 | 描述 |
| ---- | ---- |
| path | 用于指定组件应等待的URL或URL数组。 |
| exact | 当此属性为
true
时,只有精确等于
path
属性的URL才会被匹配。 |
| sensitive | 当此属性为
true
时,URL匹配区分大小写。 |
| strict | 当此属性为
true
时,以
/
结尾的
path
值只会匹配相应段也以
/
结尾的URL。 |
| component | 用于指定当
path
属性匹配浏览器的当前URL时要显示的单个组件。 |
| render | 用于指定一个函数,该函数返回当
path
属性匹配浏览器的当前URL时要显示的内容。 |
| children | 用于指定一个函数,该函数始终会渲染内容,即使
path
属性指定的URL不匹配。 |
2.5 选择组件和内容
可以使用
component
属性或
render
属性来选择要显示的组件和内容。
-
component属性
:直接指定要显示的组件类型,示例代码如下:
<Route path="/products" component={ ProductDisplay } />
需要注意的是,
component
属性的值不应该是一个函数,否则每次应用更新时都会创建一个新的组件实例。
-
render属性
:用于更复杂的内容和传递属性,示例代码如下:
import React, { Component } from "react";
import { BrowserRouter as Router, Link, Route } from "react-router-dom";
import { ProductDisplay } from "./ProductDisplay";
import { SupplierDisplay } from "./SupplierDisplay";
export class Selector extends Component {
render() {
return <Router>
<div className="container-fluid">
<div className="row">
<div className="col-2">
<div><Link to="/products">Products</Link></div>
<div><Link to="/suppliers">Suppliers</Link></div>
</div>
<div className="col">
<Route path="/products" render={ (routeProps) =>
<ProductDisplay myProp="myValue" /> } />
<Route path="/suppliers" render={ (routeProps) =>
<React.Fragment>
<h4 className="bg-info text-center text-white p-2">
Suppliers
</h4>
<SupplierDisplay />
</React.Fragment>
} />
</div>
</div>
</div>
</Router>
}
}
在这个示例中,通过
render
属性传递了一个属性给
ProductDisplay
组件,并将
SupplierDisplay
组件包含在一个更大的内容片段中。
综上所述,通过使用数据存储API和URL路由,我们可以更好地管理组件与数据存储之间的连接,以及实现应用的路由功能,从而使应用结构更清晰,易于扩展和维护。在实际开发中,根据具体需求选择合适的方法和属性,以达到最佳的开发效果。
React开发:数据存储API与URL路由的应用
3. URL路由的高级应用
在掌握了URL路由的基本使用方法后,我们可以进一步探讨其高级应用,以满足更复杂的开发需求。
3.1 精确匹配URL
在某些情况下,我们需要精确匹配URL,以确保只有特定的URL才能触发相应的组件渲染。可以使用
Route
组件的
exact
属性来实现这一功能。例如:
<Route exact path="/products" component={ ProductDisplay } />
当
exact
属性为
true
时,只有当浏览器的URL精确等于
/products
时,
ProductDisplay
组件才会被显示。
3.2 匹配多个URL
如果需要匹配多个URL,可以将
path
属性指定为一个URL数组,或者使用正则表达式。以下是使用URL数组的示例:
<Route path={["/products", "/items"]} component={ ProductDisplay } />
在这个示例中,当浏览器的URL为
/products
或
/items
时,
ProductDisplay
组件都会被显示。
3.3 选择单个路由
在某些情况下,我们可能只希望匹配一个路由,即使有多个
Route
组件的
path
属性都能匹配当前URL。可以使用
Switch
组件来实现这一功能。示例代码如下:
import { BrowserRouter as Router, Link, Route, Switch } from "react-router-dom";
<Router>
<div>
<Switch>
<Route exact path="/" component={ Home } />
<Route path="/products" component={ ProductDisplay } />
<Route path="/suppliers" component={ SupplierDisplay } />
<Route component={ NotFound } />
</Switch>
</div>
</Router>
在这个示例中,
Switch
组件会遍历所有的
Route
组件,并只渲染第一个匹配的路由。如果没有匹配的路由,则会渲染最后一个没有
path
属性的
Route
组件,通常用于显示404页面。
3.4 定义回退路由
当用户导航到一个没有匹配路由的URL时,我们可以定义一个回退路由,将用户重定向到一个默认的页面。可以使用
Redirect
组件来实现这一功能。示例代码如下:
import { BrowserRouter as Router, Link, Route, Switch, Redirect } from "react-router-dom";
<Router>
<div>
<Switch>
<Route exact path="/" component={ Home } />
<Route path="/products" component={ ProductDisplay } />
<Route path="/suppliers" component={ SupplierDisplay } />
<Redirect to="/" />
</Switch>
</div>
</Router>
在这个示例中,如果用户导航到一个没有匹配路由的URL,
Redirect
组件会将用户重定向到根路径
/
。
3.5 指示活动路由
在导航菜单中,我们通常希望突出显示当前活动的路由。可以使用
NavLink
组件来实现这一功能。
NavLink
组件与
Link
组件类似,但它会根据当前URL自动添加一个活动类名。示例代码如下:
import { BrowserRouter as Router, NavLink, Route, Switch } from "react-router-dom";
<Router>
<div>
<nav>
<NavLink to="/" exact activeClassName="active">Home</NavLink>
<NavLink to="/products" activeClassName="active">Products</NavLink>
<NavLink to="/suppliers" activeClassName="active">Suppliers</NavLink>
</nav>
<Switch>
<Route exact path="/" component={ Home } />
<Route path="/products" component={ ProductDisplay } />
<Route path="/suppliers" component={ SupplierDisplay } />
</Switch>
</div>
</Router>
在这个示例中,当用户导航到某个路由时,对应的
NavLink
组件会添加一个
active
类名,我们可以通过CSS来为这个类名设置样式,以突出显示当前活动的路由。
4. 路由配置的流程图
下面是一个简单的路由配置流程图,展示了URL路由的基本流程:
graph TD;
A[用户点击链接] --> B[URL改变];
B --> C{是否匹配路由};
C -- 是 --> D[显示匹配的组件];
C -- 否 --> E[显示404页面或重定向];
5. 总结
通过本文的介绍,我们深入了解了React开发中数据存储API和URL路由的使用方法。数据存储API可以帮助我们管理组件与数据存储之间的连接,包括添加属性、映射函数属性、合并属性和设置连接选项等。URL路由则可以使我们的应用结构更清晰,易于扩展和维护,通过使用
Router
、
Link
、
Route
等组件,我们可以实现基本的路由功能,并通过一些高级应用,如精确匹配URL、选择单个路由、定义回退路由等,满足更复杂的开发需求。
在实际开发中,我们可以根据具体需求选择合适的数据存储API和URL路由方法,以达到最佳的开发效果。同时,要注意进行全面的测试,确保所有的URL都能正确处理并显示适当的内容。
以下是一个总结表格,对比了数据存储API和URL路由的特点和应用场景:
| 技术 | 特点 | 应用场景 |
| ---- | ---- | ---- |
| 数据存储API | 管理组件与数据存储的连接,可进行属性映射和合并 | 需要共享状态数据,对组件状态进行管理的场景 |
| URL路由 | 基于URL选择显示的内容,无需共享状态数据 | 复杂应用,需要清晰的项目结构和易于扩展维护的场景 |
希望本文对你在React开发中使用数据存储API和URL路由有所帮助。在实际项目中,不断实践和探索,以更好地掌握这些技术。
超级会员免费看
38

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



