Angular 路由和状态处理问题

Angular routing and state handling problems

我有 3 个嵌套状态:

$stateProvider
        .state('A', {                    
            url: '/a',
            templateProvider: function ($templateCache) {

                return $templateCache.get('pages/a.html');
            },
            controller: 'aController'
        })

        .state('A.B', {
            url: '/b',
            templateProvider: function ($templateCache) {

                return $templateCache.get('pages/b.html');
            }
            controller: 'bController'
        })

        .state('A.B.C', {
            url: '/c',                    
            templateProvider: function ($templateCache) {

                return $templateCache.get('pages/c.html');
            },
            controller: 'cController'
        })

假设 A 是应用程序的初始状态。现在,当在状态 A 中单击状态 B 的 link 时, $state.go('.B', ...) 被调用,状态 B 必须从 A 获取参数,以便它可以调用一些使用该参数提供服务并呈现数据。

同样,当在状态 B 上单击状态 C 的 link 时,C 必须从 B 获取参数才能正常工作并正确显示数据。

第一题:

在线传递这些参数的最佳方式是什么?嵌套控制器使父作用域在子作用域中可见是错误的吗?还是应该将它们作为参数传递?

第二个问题(有点依赖于第一个问题的答案):

html 模板应该如何构建(特别是关于 'ui-view' 指令),所以当浏览器后退按钮从 B 进入状态 C 后被点击时,模板的控制器B 不会被触发,因此状态 B 显示与进入状态 C 之前相同的数据而无需重新加载。从 A 进入状态 B 后点击返回状态 B 也是如此。

第三题:

如果用户进行了以下转换:A->B->C,然后导航到某个不相关的状态 D(例如通过单击主菜单上的 link),然后在状态 D 按下后退按钮,如何防止控制器 C 崩溃,因为它没有输入参数?

第四题(与第三题相关):

前提: 进入状态 B 的唯一 'right' 方法是点击状态 A,同样要进入 C,用户必须通过 A->乙第一。

那么,当用户从一些不相关的状态 D 手动输入 URL B 时,我该如何处理?同样,一切都崩溃了,因为 B 没有输入参数。

谢谢。

第1、3、4题可以在你的状态url上使用参数来解决。例如,状态 A.B 的 URL 可以是 /b?x&y&z 而不仅仅是 /b。然后要从 A 过渡到 A.B,您将使用:

$state.go('A.B', {x: "val1", y: "val2", z: "val3"});

这解决了第一个问题,因为您将参数从 A 传递到 B。这解决了第三个问题,因为状态 A.B.C 从另一个状态返回后不会崩溃,因为 URL history 包含参数。很明显,这种方法将如何解决用户直接在地址栏中输入 URL 的第四个问题。

问题 2 提出了一个稍微难解决的问题。但是你可以做的是在 A 和 B 之间引入一个中间状态,其唯一目的是防止在按下后退按钮时重新加载状态 A 的控制器。

.state('A', {
            abstract: true,                    
            url: '/a',
            templateProvider: function ($templateCache) {

                return $templateCache.get('pages/a.html');
            },
            controller: 'aController'
        })
.state('A.int', {

            url: '/a/view',
            template: <div></div>,
            controller: 'aIntermediateController'
        })
        .state('A.int.B', {
            url: '/b',
            templateProvider: function ($templateCache) {

                return $templateCache.get('pages/b.html');
            }
            controller: 'bController'
        })

注意,我将状态 A 抽象化,这样您就无法直接导航到它。相反,您直接导航到 A.int。当您最初加载状态 A.int 时,aController 将在 aIntermediateController 执行之前执行一次。随后,任何对 A.int 的状态更改将只执行一个中间控制器。这就是您可以多次阻止 aController 运行 的方法。 同样的,你可以用同样的方法在B状态和C状态之间添加一个中间视图。