如何有效地构建AngularUI ui-router状态机?

时间:2022-01-12 11:30:11

I am very new to the new AngularUI ui-router library that allows us to create nested views using a state machine configuration service and am trying to figure out the best way to architect my states. I am creating an application that uses nested views but my implementation is a little bit different than many of the examples I have been seeing.

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

The ui-router demo shows how nested views are achieved using the state machine syntax {parent}.{child}.{grandchild} where parent can have the equivalent route /home, /order, /about, etc.

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

Lets architect out a sample website now. Lets say at the top most level we have 3 views we want to render. The 3 views are /home, /order, and /about. All of these views are basically siblings as far as ui-router is concerned. However, we need an abstract state for the actual root of our application. This state we will call root.

让建筑师现在建立一个样本网站。让我们说在最顶层我们有3个视图我们想要渲染。 3个视图是/ home,/ order和/ about。就ui-router而言,所有这些视图基本上都是兄弟姐妹。但是,我们需要一个抽象状态来表示应用程序的实际根。这个状态我们称之为root。

$stateProvider.
    .state('root', {
        abstract: true
        url: '/',
        templateUrl: 'templates/index.html`
    })

templates/index.html

模板/ index.html的

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>
    <div ui-view></div>
</body>
</html>

Now since root is abstract, we cannot just go directly to / to see our pages, we must invoke one of the child states home, about, or order. Lets create these states

现在因为root是抽象的,我们不能直接去/看到我们的页面,我们必须调用其中一个子状态为home,about或order。让我们创建这些状态

$stateProvider
    .state('home', {
        url:'',
        templateUrl: 'templates/home.html'
    })
    .state('about', {
        url:'/about',
        templateUrl: 'templates/about.html'
    })
    .state('order', {
        url:'/order',
        templateUrl: 'templates/order.html'
    })

Now, if we navigate to /, /about, or /order, we get routed to home, about, and order states respectively. This seems pretty trivial so far, so lets get a little more complicated.

现在,如果我们导航到/,/ about或/ order,我们将分别路由到home,about和order状态。到目前为止,这看起来非常简单,所以让我们变得更复杂一些。

The home and about pages are fairly straight forward and require no extra work, but what if we want to make our order page have internal functionality such as an overview page, an accounts page, and a billings page. Now, navigating to order will actually bring us to overview which will have a nav menu to then travel between overview,accounts, andbillings`.

家庭和关于页面是相当直接的,不需要额外的工作,但如果我们想要使我们的订单页面具有内部功能,例如概述页面,帐户页面和帐单页面,该怎么办。现在,导航到订单实际上将使我们进入概览,其中将有一个导航菜单,然后在概览,帐户和帐单之间旅行。

To get this functionality, we once again have to make order abstract. Doing so allows us to just use a simple ui-view directive that will be used to render either overview, accounts, and billings.

为了获得这个功能,我们再一次必须使订单抽象化。这样做只允许我们使用一个简单的ui-view指令,该指令将用于呈现概述,帐户和账单。

templates/order.html

模板/ order.html

<ul id="navMenu">
        <li ui-sref-active="active"><a ui-sref="">Back</a></li>
        <li ui-sref-active="active"><a ui-sref=".overview">Overview</a></li>
        <li ui-sref-active="active"><a ui-sref=".accounts" >Accounts</a></li>
        <li ui-sref-active="active"><a ui-sref=".billing">Billing</a></li>
</ul>

<div ui-view></div>

Now our $stateProvider will get the following added on

现在我们的$ stateProvider将添加以下内容

$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'
    })

Notice the order state was modified from before so now it is abstract and can only be accessed by navigating to one of it's children states. Here is where the actual question comes into place. Right now, our "state" tree looks something like

请注意,订单状态已从之前修改过,因此现在它是抽象的,只能通过导航到其中一个子状态来访问。这是实际问题到位的地方。现在,我们的“状态”树看起来像

                          root (abstract)
                           / |  \
                          /  |   \
                         /   |    \
                        /    |     \
                     home  order  about
                           / |  \
                          /  |   \
                         /   |    \
                        /    |     \
                       /     |      \
                overview  accounts billing

And everything looks great, but lets say now we want there to be another level under accounts to look at account details. We want the accounts page to have a table of accounts that can be clicked on. When clicked, we want the ENTIRE view to change to an account details page. This page's URL transition from accounts to account.details looks something like

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

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

to

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

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.

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

I am trying to figure out what the correct way to architect an entire website like this using the state machine design that ui-router provides. This means knowing when to use an abstract state and when not to.

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

Could someone show an example of how a complex site is architected using these techniques?

有人可以展示一个如何使用这些技术构建复杂网站的示例吗?

1 个解决方案

#1


1  

A couple of things here:

这里有几件事:

This paragraph implies a code smell:

本段暗示代码气味:

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.

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

Your states are not aligning with your views. In general, you should be ensuring this is the case, and I'd try to re-archtect things so that there is alignment. It's best to do this early on before you go too deep into your implementation since things will just get more complex over time. You'll find yourself fighting against the state machine instead of working with it.

您的州没有与您的观点保持一致。一般来说,你应该确保这种情况,并且我会尝试重新检测事物,以便有一致性。最好在你深入实施之前尽早这样做,因为随着时间的推移,事情会变得更加复杂。你会发现自己正在与国家机器作斗争而不是使用它。

Now, there may be a way to get what you want without making any changes to your transitions. The problem you have is not with the states, but the fact that when you transition to a sibling state, the parent state's view is not being refreshed. There are some options that you can use. See the documentation for ui-router $state.

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

It's likely that you will need to call $state.reload after the transition occurs. Be careful that you don't go into an infinite loop.

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

#1


1  

A couple of things here:

这里有几件事:

This paragraph implies a code smell:

本段暗示代码气味:

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.

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

Your states are not aligning with your views. In general, you should be ensuring this is the case, and I'd try to re-archtect things so that there is alignment. It's best to do this early on before you go too deep into your implementation since things will just get more complex over time. You'll find yourself fighting against the state machine instead of working with it.

您的州没有与您的观点保持一致。一般来说,你应该确保这种情况,并且我会尝试重新检测事物,以便有一致性。最好在你深入实施之前尽早这样做,因为随着时间的推移,事情会变得更加复杂。你会发现自己正在与国家机器作斗争而不是使用它。

Now, there may be a way to get what you want without making any changes to your transitions. The problem you have is not with the states, but the fact that when you transition to a sibling state, the parent state's view is not being refreshed. There are some options that you can use. See the documentation for ui-router $state.

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

It's likely that you will need to call $state.reload after the transition occurs. Be careful that you don't go into an infinite loop.

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