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

sjt*_*003 71 javascript angularjs angularjs-scope angular-ui-router

如果不在父控制器中使用服务或构建观察者,那么如何让儿童状态访问主控制器$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'
  })  
Run Code Online (Sandbox Code Playgroud)

我无法在子状态下访问mainController范围 - 或者说我正在获取该范围的另一个实例 - 而不是我想要的.我觉得我错过了一些简单的事情.状态对象中有一个共享数据配置选项,但我不确定是否应将此类用于此类.

Rad*_*ler 107

创建了工作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'
  })  
Run Code Online (Sandbox Code Playgroud)

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

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

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

好吧,我所说的是:只有父州才会启动$scope.Model.所有其他人都会得到充分的.怎么样?那么这里是答案:

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

请记住,只有嵌套状态的视图时,范围属性才会继承状态链.范围属性的继承与状态的嵌套以及与视图(模板)的嵌套有关的所有内容都无关.

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

因此,正如文档中所述.由于我们的子视图嵌套在父视图中,因此范围是继承的.

了解范围

在AngularJS中,子范围通常原型继承自其父范围.
...

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

// So, use
<input type="text" ng-model="someObj.prop1"> 
// rather than
<input type="text" ng-model="prop1">.
Run Code Online (Sandbox Code Playgroud)

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

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

这里查看工作示例

  • 这是非常有用的信息.感谢您花时间以有序的方式解释这一点 - 这种水平的蒸馏不会被忽视.我按照你的建议重建了stateProvider.state对象和我的模板,一切都按照我希望的方式工作:范围继承了链 - 我觉得在构建视图时不考虑这个基本原则很傻 - 再次感谢你我希望所有关于SO的答案都经过深思熟虑. (9认同)

Mic*_*ole 15

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

以下是如何执行多步骤表单.我需要路由来包含有关它们在流程中的步骤的信息.

首先,我有一些UI路由器的路由:

  // 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'},
  })
Run Code Online (Sandbox Code Playgroud)

注意:

  • data每条路线中的元素.
  • abstract州有SignupController.这是这个多步形式的唯一控制器.这abstract不是必需的,但对这个用例有意义.

SignupController.js

angular.module('app').controller('SignupController', function($scope, $state) {
  $scope.state = $state;
});
Run Code Online (Sandbox Code Playgroud)

在这里,我们得到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>
Run Code Online (Sandbox Code Playgroud)

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

  • 如果你想简化视图模板中的$状态,你可以这样做:`$ scope.state = $ state.current.data;`并在视图中:`{{state.title}}` (2认同)

Ben*_*ant 9

这个想法是你在parent-> child inheritance中使用scope:

 .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'
  })  
Run Code Online (Sandbox Code Playgroud)

用法很简单,你有3个控制器,一个是共享的(mainController),每个视图都有它自己的.

  • 然后使用:$ scope.$ parent访问子控制器中父级的$ scope (2认同)

Bah*_*ere 7

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

.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"
        })
Run Code Online (Sandbox Code Playgroud)

  • 如果我想分别为child1和child2使用child1Controller和child2Controller,该怎么办? (3认同)