关于 angularjs:如何高效地架构 AngularUI ui-router 状态机?

How to efficiently architect the AngularUI ui-router state machine?

我对新的 AngularUI ui-router 库非常陌生,它允许我们使用状态机配置服务创建嵌套视图,并且我正在尝试找出构建我的状态的最佳方法。我正在创建一个使用嵌套视图的应用程序,但我的实现与我看到的许多示例略有不同。

ui-router 演示展示了如何使用状态机语法 {parent}.{child}.{grandchild} 实现嵌套视图,其中 parent 可以具有等效的路由 /home/order/about 等。

现在让我们构建一个示例网站。假设在最顶层,我们有 3 个要渲染的视图。这 3 个视图是 /home/order/about。就 ui-router 而言,所有这些视图基本上都是同级的。但是,我们需要为应用程序的实际根提供一个抽象状态。这个状态我们将调用 root.

1
2
3
4
5
6
$stateProvider.
    .state('root', {
        abstract: true
        url: '/',
        templateUrl: 'templates/index.html`
    })

模板/index.html

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
   
</head>
<body>
   
</body>
</html>

现在由于 root 是抽象的,我们不能直接到 / 来查看我们的页面,我们必须调用子状态 homeaboutorder 之一。让我们创建这些状态

1
2
3
4
5
6
7
8
9
10
11
12
13
$stateProvider
    .state('home', {
        url:'',
        templateUrl: 'templates/home.html'
    })
    .state('about', {
        url:'/about',
        templateUrl: 'templates/about.html'
    })
    .state('order', {
        url:'/order',
        templateUrl: 'templates/order.html'
    })

现在,如果我们导航到 //about/order,我们将分别路由到 homeaboutorder 状态。到目前为止,这似乎很微不足道,所以让我们再复杂一点。

homeabout 页面相当简单,不需要额外的工作,但是如果我们想让我们的 order 页面具有内部功能,例如 overview 页面,accounts 页面怎么办, 和一个 billings 页面。现在,导航到 order 实际上会将我们带到 overview,它将有一个导航菜单,然后在 overview,accounts, andbillings` 之间移动。

为了获得这个功能,我们必须再次将 order 抽象化。这样做允许我们只使用一个简单的 ui-view 指令,该指令将用于渲染 overviewaccountsbillings

模板/order.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<ul id="navMenu">
        <li ui-sref-active="active">Back
</li>

        <li ui-sref-active="active">Overview
</li>

        <li ui-sref-active="active">Accounts
</li>

        <li ui-sref-active="active">Billing
</li>


</ul>

现在我们的 $stateProvider 将在

上添加以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$stateProvider
    .state('order', {
        abstract: true,
        url: '/order/:id',
        templateUrl: 'templates/order.html'
    })
    .state('order.overview', {
        url: '/overview',
        templateUrl: 'templates/order.overview.html'
    })
    .state('order.accounts', {
        url: '/accounts',
        templateUrl: 'templates/order.accounts.html'
    })
    .state('order.billing', {
        url: '/billing',
        templateUrl: 'templates/order.billing.html'
    })

注意 order 状态是从以前修改的,所以现在它是抽象的,只能通过导航到它的一个子状态来访问。这是实际问题出现的地方。现在,我们的"状态"树看起来像

1
2
3
4
5
6
7
8
9
10
11
12
                          root (abstract)
                           / |  \\
                          /  |   \\
                         /   |    \\
                        /    |     \\
                     home  order  about
                           / |  \\
                          /  |   \\
                         /   |    \\
                        /    |     \\
                       /     |      \\
                overview  accounts billing

一切看起来都很棒,但是现在我们希望在 accounts 下有另一个级别来查看帐户详细信息。我们希望 accounts 页面有一个可以点击的帐户表。单击后,我们希望整个视图更改为帐户详细信息页面。此页面从 accountsaccount.details 的 URL 转换看起来像

1
/order/:orderId/accounts OR /order/3/accounts

1
/order/:orderId/accounts/:accountId OR /order/3/accounts/71

这意味着转到帐户 ID 为 71 的订单 3 并查看详细信息页面。然而,在 ui-router 中,accounts.details 视图实际上是 accounts 的兄弟,因为我们希望整个视图切换到 details 而不仅仅是 accounts 内部的另一个嵌套视图。这样做的问题是我们不再遵循 ui-router 设计的状态层次结构。从概念的angular来看,帐户详细信息是 accounts 的子状态,但我们希望视图呈现为 AngularUI 状态视图,作为 accounts 的兄弟。

我正在尝试找出使用 ui-router 提供的状态机设计来构建这样的整个网站的正确方法。这意味着知道何时使用抽象状态,何时不使用。

有人可以举例说明如何使用这些技术构建复杂网站吗?


这里有几件事:

这一段暗示代码味道:

Which translates to go to Order 3 with the account Id 71 and view the details page. However in ui-router the accounts.details view is actually a sibling of accounts because we want the entire view to switch over to details instead of just another nested view INSIDE of accounts. The problem with this is we no longer are following the state hierarchy that ui-router is designed for. In a conceptual stand-point, the account details is a child state of accounts, but we want the view to render as an AngularUI state view as a sibling of accounts.

您的状态与您的观点不一致。一般来说,您应该确保是这种情况,并且我会尝试重新设计事物以便对齐。最好在您深入实施之前尽早执行此操作,因为随着时间的推移事情会变得更加复杂。您会发现自己与状态机作斗争,而不是使用它。

现在,可能有一种方法可以在不对过渡进行任何更改的情况下获得您想要的内容。您遇到的问题不在于状态,而是当您转换到同级状态时,父状态的视图没有被刷新。您可以使用一些选项。请参阅 ui-router $state.

的文档

您可能需要在转换发生后调用 $state.reload。小心不要进入无限循环。