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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27696612/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 00:31:11  来源:igfitidea点击:

How do I share $scope data between states in angularjs ui-router?

javascriptangularjsangularjs-scopeangular-ui-router

提问by sjt003

Without using a service or constructing watchers in the parent controller, how would one give children states access to the main controller's $scope.

如果不使用服务或在父控制器中构建观察者,如何让子状态访问主控制器的$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'
  })  

I'm not able to access the mainController scope in child state--or rather I'm getting another instance of that scope--not what I want. I feel I'm missing something simple. There is a shared data config option in the state object but I'm not sure if this should be used for something like this.

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

回答by Radim K?hler

I created working plunker, showing how to use $scopeand UI-Router.

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

The state definition is unchanged:

状态定义不变:

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

But each state can have different controller. Why? because each viewof each stategets newinstanceof defined controller. So while we have mainControllerlike the one below, we can be sure, that if we navigate to state 'main.2'it will be instantiated twice.

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

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

But what we can see here, is that we check if $scope.Modelalready exsits... and if not (Parent state)we instantiate it with new intance{Name : "xxx"}.

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

Well, what I am saying is: only parent state will init the $scope.Model. All others will get that already filled. How? Well here is the answer:

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

Scope Inheritance by View Hierarchy Only

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

Keep in mind that scope properties only inherit down the state chain if the views of your states are nested. Inheritance of scope properties has nothing to do with the nesting of your states and everything to do with the nesting of your views (templates).

It is entirely possible that you have nested states whose templates populate ui-views at various non-nested locations within your site. In this scenario you cannot expect to access the scope variables of parent state views within the views of children states.

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

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

So, as stated in the documentation. Because our child views are nested in the parent view, the scope is inherited.

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

Understanding Scopes

了解作用域

In AngularJS, a child scope normally prototypically inherits from its parent scope.
...

Having a '.' in your models will ensure that prototypal inheritance is in play.

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

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

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

And that's it. We get inheritance from UI-Routerviews and angular scopes, and because we smartly used a reference type (Model), i.e. do have '.'dot in ng-modeldefinition - we can share data now

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

NOTE: having dot '.' in the ng-model="Model.PropertyNamesimply means, that there is a referenceobject Model {}with some property: PropertyName

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

Check the working example here

此处检查工作示例

回答by Michael Cole

You can get the whole scope through $rootScope. If you need just part of the scope, ui-router has a custom datafeature.

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

Here's how to do a multi-step form. I needed the routes to contain info for about their steps in the flow.

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

First, I have some routes with 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'},
  })

Notice:

注意:

  • the dataelement in each route.
  • The abstractstate has SignupController. That's the only controller for this multi-step form. The abstractisn't required, but makes sense for this use case.
  • data每个路由中的元素。
  • abstract州有SignupController。这是此多步表单的唯一控制器。该abstract不是必需的,但是是有道理的,这个用例。

SignupController.js

注册控制器.js

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

Here we get ui-router's $stateand put it on $scope

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

Here is the main template 'sign-up/index.html',:

这是主模板“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>

The child templates can be whatever they like.

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

回答by Ben Diamant

The idea is that you use scope in parent->child inheritance:

这个想法是你在 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'
  })  

Than the usage is simple, you have 3 controllers, one is shared (mainController) and each view has it's own.

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

回答by Bahtiyar ?zdere

If you are using nested views just dont write any other Controller. By this way they will share same Controller Data.

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

.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"
        })

回答by hugsbrugs

Isn't the simplest solution to group shared variables into a service you can access in every controller ? ...

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