Javascript AngularJS:如何在控制器之间传递变量?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12008908/
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 06:53:17  来源:igfitidea点击:

AngularJS: How can I pass variables between controllers?

javascriptangularjsangularjs-controller

提问by dopatraman

I have two Angular controllers:

我有两个 Angular 控制器:

function Ctrl1($scope) {
    $scope.prop1 = "First";
}

function Ctrl2($scope) {
    $scope.prop2 = "Second";
    $scope.both = Ctrl1.prop1 + $scope.prop2; //This is what I would like to do ideally
}

I can't use Ctrl1inside Ctrl2because it is undefined. However if I try to pass it in like so…

我不能使用Ctrl1insideCtrl2因为它是未定义的。但是,如果我尝试像这样传递它......

function Ctrl2($scope, Ctrl1) {
    $scope.prop2 = "Second";
    $scope.both = Ctrl1.prop1 + $scope.prop2; //This is what I would like to do ideally
}

I get an error. Does anyone know how to do this?

我收到一个错误。有谁知道如何做到这一点?

Doing

正在做

Ctrl2.prototype = new Ctrl1();

Also fails.

也失败了。

NOTE:These controllers are not nested inside each other.

注意:这些控制器没有相互嵌套。

回答by Gloopy

One way to share variables across multiple controllers is to create a serviceand inject it in any controller where you want to use it.

在多个控制器之间共享变量的一种方法是创建一个服务并将其注入到您想要使用它的任何控制器中。

Simple service example:

简单的服务示例:

angular.module('myApp', [])
    .service('sharedProperties', function () {
        var property = 'First';

        return {
            getProperty: function () {
                return property;
            },
            setProperty: function(value) {
                property = value;
            }
        };
    });

Using the service in a controller:

在控制器中使用服务:

function Ctrl2($scope, sharedProperties) {
    $scope.prop2 = "Second";
    $scope.both = sharedProperties.getProperty() + $scope.prop2;
}

This is described very nicely in this blog(Lesson 2 and on in particular).

这在这个博客中有很好的描述(特别是第 2 课及以后)。

I've found that if you want to bind to these properties across multiple controllers it works better if you bind to an object's property instead of a primitive type (boolean, string, number) to retain the bound reference.

我发现如果你想跨多个控制器绑定到这些属性,如果你绑定到对象的属性而不是原始类型(布尔值、字符串、数字)来保留绑定引用,那么效果会更好。

Example: var property = { Property1: 'First' };instead of var property = 'First';.

示例:var property = { Property1: 'First' };代替var property = 'First';.



UPDATE:To (hopefully) make things more clear here is a fiddlethat shows an example of:

更新:为了(希望)让事情更清楚,这里有一个小提琴,显示了一个例子:

  • Binding to static copies of the shared value (in myController1)
    • Binding to a primitive (string)
    • Binding to an object's property (saved to a scope variable)
  • Binding to shared values that update the UI as the values are updated (in myController2)
    • Binding to a function that returns a primitive (string)
    • Binding to the object's property
    • Two way binding to an object's property
  • 绑定到共享值的静态副本(在 myController1 中)
    • 绑定到原语(字符串)
    • 绑定到对象的属性(保存到作用域变量)
  • 绑定到在值更新时更新 UI 的共享值(在 myController2 中)
    • 绑定到返回原语(字符串)的函数
    • 绑定到对象的属性
    • 两种方式绑定到对象的属性

回答by Dmitri Zaitsev

I like to illustrate simple things by simple examples :)

我喜欢用简单的例子来说明简单的事情:)

Here is a very simple Serviceexample:

这是一个非常简单的Service例子:


angular.module('toDo',[])

.service('dataService', function() {

  // private variable
  var _dataObj = {};

  // public API
  this.dataObj = _dataObj;
})

.controller('One', function($scope, dataService) {
  $scope.data = dataService.dataObj;
})

.controller('Two', function($scope, dataService) {
  $scope.data = dataService.dataObj;
});

And here the jsbin

这里的jsbin

And here is a very simple Factoryexample:

这是一个非常简单的Factory例子:


angular.module('toDo',[])

.factory('dataService', function() {

  // private variable
  var _dataObj = {};

  // public API
  return {
    dataObj: _dataObj
  };
})

.controller('One', function($scope, dataService) {
  $scope.data = dataService.dataObj;
})

.controller('Two', function($scope, dataService) {
  $scope.data = dataService.dataObj;
});

And here the jsbin

这里的jsbin



If that is too simple, here is a more sophisticated example

如果这太简单了,这里有一个更复杂的例子

Also see the answer here for related best practices comments

请参阅此处的答案以获取相关的最佳实践评论

回答by AFP_555

--- I know this answer is not for this question, but I want people who reads this question and want to handle Services such as Factories to avoid trouble doing this ----

--- 我知道这个答案不是针对这个问题的,但我希望阅读这个问题并想要处理诸如工厂之类的服务的人避免这样做的麻烦 ----

For this you will need to use a Service or a Factory.

为此,您需要使用服务或工厂。

The services are the BEST PRACTICEto share data between not nested controllers.

这些服务是在非嵌套控制器之间共享数据的最佳实践

A very very good annotation on this topic about data sharing is how to declare objects. I was unlucky because I fell in a AngularJS trap before I read about it, and I was very frustrated. So let me help you avoid this trouble.

关于这个关于数据共享的主题,一个非常好的注释是如何声明对象。我很倒霉,因为我在读到它之前就掉入了 AngularJS 的陷阱,我非常沮丧。所以让我来帮你避免这个麻烦。

I read from the "ng-book: The complete book on AngularJS" that AngularJS ng-models that are created in controllers as bare-data are WRONG!

我从“ng-book: The complete book on AngularJS”中读到,在控制器中作为裸数据创建的 AngularJS ng-models 是错误的!

A $scope element should be created like this:

$scope 元素应该像这样创建:

angular.module('myApp', [])
.controller('SomeCtrl', function($scope) {
  // best practice, always use a model
  $scope.someModel = {
    someValue: 'hello computer'
  });

And not like this:

而不是这样:

angular.module('myApp', [])
.controller('SomeCtrl', function($scope) {
  // anti-pattern, bare value
  $scope.someBareValue = 'hello computer';
  };
});

This is because it is recomended(BEST PRACTICE) for the DOM(html document) to contain the calls as

这是因为建议(最佳实践)为 DOM(html 文档)包含调用作为

<div ng-model="someModel.someValue"></div>  //NOTICE THE DOT.

This is very helpful for nested controllers if you want your child controller to be able to change an object from the parent controller....

如果您希望子控制器能够从父控制器更改对象,这对嵌套控制器非常有用....

But in your case you don't want nested scopes, but there is a similar aspect to get objects from services to the controllers.

但是在您的情况下,您不需要嵌套范围,但是从服务到控制器获取对象也有类似的方面。

Lets say you have your service 'Factory' and in the return space there is an objectA that contains objectB that contains objectC.

假设您有您的服务“工厂”,并且在返回空间中有一个包含 objectB 的 objectA,其中包含 objectC。

If from your controller you want to GET the objectC into your scope, is a mistake to say:

如果您想从您的控制器中将 objectC 获取到您的范围内,那么说:

$scope.neededObjectInController = Factory.objectA.objectB.objectC;

That wont work...Instead use only one dot.

那行不通……而是只使用一个点。

$scope.neededObjectInController = Factory.ObjectA;

Then, in the DOM you can call objectC from objectA. This is a best practice related to factories, and most important, it will help to avoid unexpected and non-catchable errors.

然后,在 DOM 中,您可以从 objectA 调用 objectC。这是与工厂相关的最佳实践,最重要的是,它将有助于避免意外和无法捕获的错误。

回答by Sanjeev

Solution without creating Service, using $rootScope:

不创建服务的解决方案,使用 $rootScope:

To share properties across app Controllers you can use Angular $rootScope. This is another option to share data, putting it so that people know about it.

要在应用程序控制器之间共享属性,您可以使用 Angular $rootScope。这是共享数据的另一种选择,让人们知道它。

The preferred way to share some functionality across Controllers is Services, to read or change a global property you can use $rootscope.

跨控制器共享某些功能的首选方法是服务,要读取或更改可以使用 $rootscope 的全局属性。

var app = angular.module('mymodule',[]);
app.controller('Ctrl1', ['$scope','$rootScope',
  function($scope, $rootScope) {
    $rootScope.showBanner = true;
}]);

app.controller('Ctrl2', ['$scope','$rootScope',
  function($scope, $rootScope) {
    $rootScope.showBanner = false;
}]);

Using $rootScope in a template (Access properties with $root):

在模板中使用 $rootScope(使用 $root 访问属性):

<div ng-controller="Ctrl1">
    <div class="banner" ng-show="$root.showBanner"> </div>
</div>

回答by Juan Zamora

The sample above worked like a charm. I just did a modification just in case I need to manage multiple values. I hope this helps!

上面的示例就像一个魅力。我只是做了一个修改,以防万一我需要管理多个值。我希望这有帮助!

app.service('sharedProperties', function () {

    var hashtable = {};

    return {
        setValue: function (key, value) {
            hashtable[key] = value;
        },
        getValue: function (key) {
            return hashtable[key];
        }
    }
});

回答by Chilledflame

I tend to use values, happy for anyone to discuss why this is a bad idea..

我倾向于使用价值观,很高兴有人讨论为什么这是一个坏主意。

var myApp = angular.module('myApp', []);

myApp.value('sharedProperties', {}); //set to empty object - 

Then inject the value as per a service.

然后根据服务注入值。

Set in ctrl1:

在 ctrl1 中设置:

myApp.controller('ctrl1', function DemoController(sharedProperties) {
  sharedProperties.carModel = "Galaxy";
  sharedProperties.carMake = "Ford";
});

and access from ctrl2:

并从 ctrl2 访问:

myApp.controller('ctrl2', function DemoController(sharedProperties) {
  this.car = sharedProperties.carModel + sharedProperties.carMake; 

});

回答by Zanon

The following example shows how to pass variables between siblingscontrollers andtake an action when the value changes.

下面的例子展示了如何在兄弟控制器之间传递变量在值改变时采取行动。

Use case example: you have a filter in a sidebar that changes the content of another view.

用例示例:您在侧栏中有一个过滤器,用于更改另一个视图的内容。

angular.module('myApp', [])

  .factory('MyService', function() {

    // private
    var value = 0;

    // public
    return {
      
      getValue: function() {
        return value;
      },
      
      setValue: function(val) {
        value = val;
      }
      
    };
  })
  
  .controller('Ctrl1', function($scope, $rootScope, MyService) {

    $scope.update = function() {
      MyService.setValue($scope.value);
      $rootScope.$broadcast('increment-value-event');
    };
  })
  
  .controller('Ctrl2', function($scope, MyService) {

    $scope.value = MyService.getValue();

    $scope.$on('increment-value-event', function() {    
      $scope.value = MyService.getValue();
    });
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="myApp">
  
  <h3>Controller 1 Scope</h3>
  <div ng-controller="Ctrl1">
    <input type="text" ng-model="value"/>
    <button ng-click="update()">Update</button>
  </div>
  
  <hr>
  
  <h3>Controller 2 Scope</h3>
  <div ng-controller="Ctrl2">
    Value: {{ value }}
  </div>  

</div>

回答by Fedaykin

I'd like to contribute to this question by pointing out that the recommended way to share data between controllers, and even directives, is by using services (factories) as it has been already pointed out, but also I'd like to provide a working practical example of how to that should be done.

我想通过指出在控制器甚至指令之间共享数据的推荐方法是使用已经指出的服务(工厂)来为这个问题做出贡献,但我也想提供一个如何做到这一点的工作实际例子。

Here is the working plunker:http://plnkr.co/edit/Q1VdKJP2tpvqqJL1LF6m?p=info

这是工作plunker:http ://plnkr.co/edit/Q1VdKJP2tpvqqJL1LF6m?p=info

First, createyour service, that will have your shared data:

首先,创建您的服务,它将拥有您的共享数据

app.factory('SharedService', function() {
  return {
    sharedObject: {
      value: '',
      value2: ''
    }
  };
});

Then, simply inject it on your controllersand grab the shared data on your scope:

然后,只需将其注入您的控制器并在您的范围内获取共享数据:

app.controller('FirstCtrl', function($scope, SharedService) {
  $scope.model = SharedService.sharedObject;
});

app.controller('SecondCtrl', function($scope, SharedService) {
  $scope.model = SharedService.sharedObject;
});

app.controller('MainCtrl', function($scope, SharedService) {
  $scope.model = SharedService.sharedObject;
});

You can also do that for your directives, it works the same way:

您也可以为您的指令执行此操作,它的工作方式相同:

app.directive('myDirective',['SharedService', function(SharedService){
  return{
    restrict: 'E',
    link: function(scope){
      scope.model = SharedService.sharedObject;
    },
    template: '<div><input type="text" ng-model="model.value"/></div>'
  }
}]);

Hope this practical and clean answer can be helpful to someone.

希望这个实用而干净的答案可以对某人有所帮助。

回答by Noahdecoco

You could do that with services or factories. They are essentially the same apart for some core differences. I found this explanation on thinkster.ioto be the easiest to follow. Simple, to the point and effective.

你可以通过服务或工厂来做到这一点。除了一些核心差异之外,它们基本上相同。我发现thinkster.io上的这个解释最容易理解。简单、中肯、有效。

回答by kJamesy

Ah, have a bit of this new stuff as another alternative. It's localstorage, and works where angular works. You're welcome. (But really, thank the guy)

啊,有一些这种新东西作为另一种选择。它是 localstorage,在 angular 起作用的地方工作。别客气。(但真的,谢谢那家伙)

https://github.com/gsklee/ngStorage

https://github.com/gsklee/ngStorage

Define your defaults:

定义默认值:

$scope.$storage = $localStorage.$default({
    prop1: 'First',
    prop2: 'Second'
});

Access the values:

访问值:

$scope.prop1 = $localStorage.prop1;
$scope.prop2 = $localStorage.prop2;

Store the values

存储值

$localStorage.prop1 = $scope.prop1;
$localStorage.prop2 = $scope.prop2;

Remember to inject ngStorage in your app and $localStorage in your controller.

请记住在您的应用程序中注入 ngStorage,在您的控制器中注入 $localStorage。