如何在 angularjs ui-router 中的状态之间共享 $scope 数据?

IT技术 javascript angularjs angularjs-scope angular-ui-router
2021-02-08 03:30:58

如果不使用服务或在父控制器中构建观察者,如何让子状态访问主控制器的$scope.

  .state("main", {
      controller:'mainController',
      url:"/main",
      templateUrl: "main_init.html"
  })  
  .state("main.1", {
      controller:'mainController',
      parent: 'main',
      url:"/1",
      templateUrl: 'form_1.html'
  })  
  .state("main.2", {
      controller:'mainController',
      parent: 'main',
      url: "/2",
      templateUrl: 'form_2.html'
  })  

我无法访问处于子状态的 mainController 范围——或者说我得到了该范围的另一个实例——这不是我想要的。我觉得我错过了一些简单的东西。状态对象中有一个共享数据配置选项,但我不确定它是否应该用于类似的事情。

5个回答

创建了工作 plunker,展示了如何使用$scope和 UI-Router。

状态定义不变:

$stateProvider
    // States
 .state("main", {
      controller:'mainController',
      url:"/main",
      templateUrl: "main_init.html"
  })  
  .state("main.1", {
      controller:'mainController',
      parent: 'main',
      url:"/1",
      templateUrl: 'form_1.html'
  })  
  .state("main.2", {
      controller:'mainController',
      parent: 'main',
      url: "/2",
      templateUrl: 'form_2.html'
  })  

但是每个状态可以有不同的控制器。为什么?因为每个view每个获得new 实例的定义controller因此,虽然我们mainController喜欢下面的那个,但我们可以肯定,如果我们导航到 state 'main.2',它将被实例化两次。

controller('mainController', function ($scope) {
  $scope.Model = $scope.Model || {Name : "xxx"};
})

但是我们在这里可以看到,我们检查是否$scope.Model已经存在......如果不是(父状态),我们用新的实例实例 化它{Name : "xxx"}

好吧,我要说的是:只有父状态会初始化$scope.Model. 所有其他人都会得到已经填满的。如何?答案是这样的:

仅按视图层次结构继承范围

请记住,如果您的状态的视图是嵌套的,那么范围属性只会沿状态链向下继承。范围属性的继承与状态的嵌套无关,而与视图(模板)的嵌套有关。

您完全有可能拥有嵌套状态,其模板在您站点内的各种非嵌套位置填充 ui 视图。在这种情况下,您不能期望在子状态的视图中访问父状态视图的范围变量。

所以,如文档中所述。因为我们的子视图嵌套在父视图中,所以作用域是继承的。

了解作用域

在 AngularJS 中,子作用域通常原型继承自其父作用域。
...

有一个 '。' 在您的模型中将确保原型继承发挥作用。

// So, use
<input type="text" ng-model="someObj.prop1"> 
// rather than
<input type="text" ng-model="prop1">.

就是这样。我们从UI-Router视图和角度范围获得继承,并且因为我们巧妙地使用了引用类型 ( Model),即定义中确实'.'有点ng-model- 我们现在可以共享数据

注意:有点 '.' ng-model="Model.PropertyName简单的手段,是有reference对象Model {}的一些属性:PropertyName

此处检查工作示例

@Radim Kohler 有什么办法可以帮助我解决这个问题 stackoverflow.com/questions/58126482/...
2021-03-21 03:30:58
这是非常有用的信息。感谢您花时间以有序的方式解释这一点——这种蒸馏水平不会被忽视。我根据你的建议重建了 stateProvider.state 对象和我的模板,一切都按照我希望的方式工作:范围沿链继承——我觉得在构建视图时没有考虑这个基本原则很愚蠢——再次感谢你我希望所有关于 SO 的答案都像这样经过深思熟虑。
2021-03-22 03:30:58
Radim,非常感谢您对 SO 的帮助!
2021-04-01 03:30:58
@Radim Kohler 我有登录状态问题。你能帮我解决我的问题吗:stackoverflow.com/questions/34690439/...
2021-04-03 03:30:58
谁知道因为如果我删除“|| {} ;” 在 mainController 里面它不起作用?
2021-04-05 03:30:58

您可以通过$rootScope获取整个范围如果您只需要部分范围,则 ui-router 具有自定义数据功能。

以下是如何制作多步表单。我需要路由来包含有关他们在流程中的步骤的信息。

首先,我有一些带有 UI-router 的路由:

  // Sign UP routes
  .state('sign-up', {
    abstract: true,
    url: '/sign-up',
    controller: 'SignupController',
    templateUrl: 'sign-up/index.html',
  })
  .state('sign-up.start', {
    url: '-start',
    templateUrl: 'sign-up/sign-up.start.html',
    data: { step: 0, title: 'Welcome to Mars!', },
  })
  .state('sign-up.expertise', {
    url: '-expertise',
    templateUrl: 'sign-up/sign-up.expertise.html',
    data: { step: 1, title: 'Your Expertise'},
  })

注意:

  • data每个路由中元素。
  • abstract州有SignupController这是此多步表单的唯一控制器。abstract不是必需的,但是是有道理的,这个用例。

注册控制器.js

angular.module('app').controller('SignupController', function($scope, $state) {
  $scope.state = $state;
});

在这里,我们得到了 ui-router$state并把它装上$scope

这是主模板“sign-up/index.html”:

<h2>{{state.current.data.title}}</h2>

<div>This is a multi-step-progress control {{state.current.data.step}}</div>

<form id="signUpForm" name="signUpForm" novalidate>
  <div ui-view></div>
</form>

子模板可以是他们喜欢的任何东西。

这为我节省了一些时间。感谢分享
2021-03-19 03:30:58
如果你想简化视图模板中的 $state,你可以这样做:$scope.state = $state.current.data;在视图中:{{state.title}}
2021-03-22 03:30:58

这个想法是你在 parent->child 继承中使用范围:

 .state("main", {
      controller:'mainController',
      abstract: true,
      url:"/main",
      templateUrl: "main_init.html"
  })  
  .state("main.1", {
      controller:'mainController1',
      parent: 'main',
      url:"/1",
      templateUrl: 'form_1.html'
  })  
  .state("main.2", {
      controller:'mainController2',
      parent: 'main',
      url: "/2",
      templateUrl: 'form_2.html'
  })  

比使用更简单,你有 3 个控制器,一个是共享的(mainController),每个视图都有它自己的。

然后在子控制器中访问父级的 $scope : $scope.$parent
2021-03-29 03:30:58
我什至没有提到“抽象:真实”就得到了范围,所以如果我不提到有什么缺点
2021-04-05 03:30:58

如果您使用嵌套视图,请不要编写任何其他控制器。通过这种方式,他们将共享相同的控制器数据。

.state("main", {
            url: "/main",
            templateUrl: "templates/Ders",
            controller: "DersController as DersC"
       }).state("main.child1", {
            url: "/child1",
            templateUrl: "templates/Ders/child1"
       }).state("main.child2", {
            url: "/child2",
            templateUrl: "templates/Ders/child2"
        })
如果我分别想要 child1 和 child2 的 child1Controller 和 child2Controller 怎么办?
2021-03-11 03:30:58

将共享变量分组到您可以在每个控制器中访问的服务中不是最简单的解决方案吗?...

这是一个简单的解决方案,但不会像(1)视图如何访问父控制器(干净地使用controller as)和(2)父控制器如何注入指令(干净地使用require),如果控制器可以有依赖的控制器实例注入他们?
2021-03-22 03:30:58