【问题标题】:Code design for the multidocument tabbed interface for React SPA with react-router/react-router-dom?带有 react-router/react-router-dom 的 React SPA 的多文档选项卡式界面的代码设计?
【发布时间】:2021-03-29 03:53:24
【问题描述】:

我有带有 react-router/react-router-dom 导航的 React SPA 应用程序,这意味着有 react-router-dom(react-router 的附加层)Switch 语句,根据路径选择:

<Switch>
    <Route path='/login' component={LoginPage}/>
    <Route path='/about' component={AboutPage}/>
    <Route exact path='/' component={HomePage}/>
    <Route path='/sales/orderlist' component={OrderListPage}/>
    <Route path='/sales/order' component={() => <OrderPage/>}/>
    <Route path='/sales/order/:id' component={() => <OrderPage/>}/>
    <Route path='/sales/invoicelist' component={InvoiceListPage}/>
    <Route path='/sales/invoice' component={InvoicePage}/>
    <Route path='/sales/invoice/:id' component={InvoicePage}/>
</Switch>

我的应用程序在导航栏中也有 react-router 链接,所以 - 这就是简单导航的工作方式。我了解执行链接“/sales/invoice/58”会执行以下 3 件事:

  1. 它实例化 InvoicePage 组件;
  2. 将 id 值 58 移动到 InvoicePage 的 props 中;
  3. 它使实例化的组件(实际上是具有大内容的元素)可见,并且所有剩余的实例化组件(如果有的话,例如 InvoiceListPage)(它们只是本身具有大内容的元素/DOM 树)可见=false。 我不确定这种向外导航是否会释放组件,我的猜测是,它们会保留在内存中(在 DOM 树中)。我也不确定当 2 次连续调用 'sales/invoice/59' 和 'sales/invoice/60' 时会发生什么 - 只有一个 InvoicePage 组件实例化,然后它的 props 属性从 59 更改为 60(可能或可能不会根据该组件中编码的业务逻辑触发全部或部分数据重新加载)?或者也许 react-router 确保两个不同的调用具有两个不同的 id 值创建两个不同的组件? (这些小问题不是应该回答的 SO 问题意义上的问题 - 我只是在这里喋喋不休,我在问题格式中列出了要考虑的要点,这些不是真正的 SO 问题)

我的问题是 - 我怎样才能将这个设计变成多标签多文档设计? 我的应用程序应该放在浏览器的一个页面/标签中,并且我的应用程序应该有应用程序级别的标签。例如。当用户按下 InvoiceList 的链接时,会打开带有 InvoiceList 报告的新应用程序选项卡。当用户选择一张明确的发票和此报告并单击链接时,将打开另一个带有发票(具有特定 ID)的应用程序选项卡。并且用户可以打开许多带有不同发票的标签。

这种多标签多文档界面的设计和想法是什么?创建一个应该非常困难和混乱。例如。标准的 react-router 在浏览器 url 字段中显示 #-link 到活动组件。但是,如果我的 SPA 应用程序有多个打开/活动的应用程序级别选项卡,其中包含多个打开的 React 组件/文档 - 那么浏览器应该显示什么链接?

Redux 支持呢 - 通常应用程序有一个应用程序范围的 Redux 存储,但现在 - 每个组件(InvoiceListPage、InvoicePage、OrderPage)都应该有自己的 Redux 存储 - 即 Redux 存储应该作为数组和整个 SPA 应用程序实现应该保留一些记录 - Redux 数组的哪个元素属于哪个组件...

只是想了解用于 web 的 React SPA 应用程序的带有 react-router 的多选项卡多文档界面的一般设计。

这种多标签 GUI 很常见 - 例如Metasfresh https://github.com/metasfresh/metasfresh 有一个,Lotus Notes 有一个,多标签界面是微软 WPF 多文档界面的首选组织(至少我前段时间读到它时是这样)。

【问题讨论】:

    标签: reactjs user-interface redux react-router tabs


    【解决方案1】:

    在 reactJS 中你有本地状态(this.state 或 useState)你有从父组件传递的状态(称为 props),你有由祖先组件传递的状态(称为上下文)你可能有来自应用程序其他部分的状态(以 redux 为例)。但所有这些,都只是“状态”,根​​据它你想在屏幕上看到什么。

    那么什么是有效的 MDI?它是一个打开文档的列表(因此您需要在您的状态中的某个位置有这样一个打开文档列表,其中每个元素都代表该特定文档的当前状态),以及一个当前打开的文档,它应该在您的某个位置状态。在您的示例中,告诉您哪个是当前打开的文档的状态是... react-router 的位置!

    因此您可以使用 redux(或创建自己的商店)并将打开的文档保存在某个地方

    //store's instance
    {
       ...,
       openDocuments:[
           { path: '/sales/invoice/1', title: 'Invoice #1', ... },
           { path: '/sales/invoice/2', title: 'Invoice #2', ... },
           { path: '/sales/order/13', title: 'Order #13', ... }
       ],
       ...
    }
    // The 'path' property of each openDocument serves as the id of that document
    // and should be unique in the array
    

    然后在您的布局中,您应该有一个选项卡式导航栏,它将每个项目呈现为一个选项卡并可能突出显示活动选项卡(通过使用 useMatch 挂钩来检查页面位置是否与该特定项目的 id 匹配)。

    在您的布局中间,您应该有您的常规&lt;Switch /&gt;,它将根据反应路由器的位置呈现实际页面。 您还可以创建一些像 useCurrentDocumentState 这样的钩子来读取当前打开文档的状态。 (例如,在该挂钩中,您将从商店中读取,在数组中找到与实际打开的文档相对应的项目并返回它

    实际上,如果您考虑一下,通常左侧导航栏(菜单项)的单页应用程序只是一种多文档界面,其中所有菜单项都被认为是“打开的”,但只有在你点击它们。

    您实际上不应该关心 DOM 中发生了什么,以及您的选项卡是否保持打开但隐藏或从 DOM 中删除。处理 DOM 是 react 的工作,实际上这也是它被构建的原因之一。这样你就不用担心 DOM。您应该只关心希望在应用程序的生命周期中为每个选项卡(选项卡的状态)保持打开什么样的信息。

    【讨论】:

      猜你喜欢
      • 2020-08-13
      • 1970-01-01
      • 1970-01-01
      • 2017-08-28
      • 1970-01-01
      • 2020-03-30
      • 2018-02-25
      • 1970-01-01
      • 2017-10-04
      相关资源
      最近更新 更多