43、React开发:数据存储API与URL路由的应用

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路由有所帮助。在实际项目中,不断实践和探索,以更好地掌握这些技术。

内容概要:本文围绕六自由度机械臂的人工神经网络(ANN)设计展开,重点研究了正向逆向运动学求解、正向动力学控制以及基于拉格朗日-欧拉法推导逆向动力学方程,并通过Matlab代码实现相关算法。文章结合理论推导仿真实践,利用人工神经网络对复杂的非线性关系进行建模逼近,提升机械臂运动控制的精度效率。同时涵盖了路径规划中的RRT算法B样条优化方法,形成从运动学到动力学再到轨迹优化的完整技术链条。; 适合人群:具备一定机器人学、自动控制理论基础,熟悉Matlab编程,从事智能控制、机器人控制、运动学六自由度机械臂ANN人工神经网络设计:正向逆向运动学求解、正向动力学控制、拉格朗日-欧拉法推导逆向动力学方程(Matlab代码实现)建模等相关方向的研究生、科研人员及工程技术人员。; 使用场景及目标:①掌握机械臂正/逆运动学的数学建模ANN求解方法;②理解拉格朗日-欧拉法在动力学建模中的应用;③实现基于神经网络的动力学补偿高精度轨迹跟踪控制;④结合RRTB样条完成平滑路径规划优化。; 阅读建议:建议读者结合Matlab代码动手实践,先从运动学建模入手,逐步深入动力学分析神经网络训练,注重理论推导仿真实验的结合,以充分理解机械臂控制系统的设计流程优化策略。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值