AngularJS:在页面的两个不同的嵌套部分*享同一控制器的数据

时间:2022-11-26 23:55:08

I want to share the data of one controller between two places in my page. For example:

我想在我的页面中的两个地方之间共享一个控制器的数据。例如:

<div ng-app="myApp">
    <div ng-controller="myController">
        <input type="text" ng-model="x" /> {{x}}
    </div>
</div>
<!-- these are in totally different places and I do not want, nor can't nest them -->
<div ng-app="myApp">
    <div ng-controller="myController">
        <input type="text" ng-model="x" /> {{x}}
    </div>
</div>

and of course, this:

当然,这个:

var myApp = angular.module('myApp', []);
myApp.controller('myController', function($scope) {
    $scope.x = 'test';
});

What can I do so that, no matter what I type first input text will be reflected in the second? And vice versa? Basically the same data being propagated to these two sections, while maintaining a single copy of the data.

我能做什么,无论我输入什么内容,第一个输入文字都会反映在第二个?反之亦然?基本上,相同的数据传播到这两个部分,同时保持数据的单个副本。

JSFiddle here: http://jsfiddle.net/LETAd/

JSFiddle:http://jsfiddle.net/LETAd/

PS: I bootstrap it manually, if this is of any relevance.

PS:我手动引导它,如果这是相关的。

Thanks!

2 个解决方案

#1


4  

To share data between controllers, normally a service is your best option. Put the shared data into the service, and inject the service into the controller:

要在控制器之间共享数据,通常服务是您的最佳选择。将共享数据放入服务,并将服务注入控制器:

function myController($scope, MyService) {

Each scope/controller instance will then be able to access the shared data.

然后,每个范围/控制器实例都可以访问共享数据。

Note that services are singletons, so there will only be one instance of your shared data around.

请注意,服务是单例,因此只有一个共享数据实例。

Here is a fiddle (I didn't write it) showing how two controllers can share data.

这是一个小提琴(我没写它),展示了两个控制器如何共享数据。

See also AngularJS: How can I pass variables between controllers? and
Angularjs: two way data bindings and controller reload.

另请参见AngularJS:如何在控制器之间传递变量?和Angularjs:双向数据绑定和控制器重新加载。

#2


3  

Ideally, you should have only one application running in a single page. Since you also need to communicate between the controllers, you should really run a single application. Possibly on body or html. Then you can create a main controller which would encapsulate all your controllers. (controller inheritance).

理想情况下,您应该只在一个页面中运行一个应用程序。由于您还需要在控制器之间进行通信,因此您应该真正运行单个应用程序。可能在身体或HTML上。然后,您可以创建一个主控制器,它将封装所有控制器。 (控制器继承)。

Here is what it should look like:

这是它应该是什么样子:

<html ng-app="myApp">
  <head>...</head>
  <body ng-controller="MainCtrl">
    <div ng-controller="MyCtrl">
      <input type="text" ng-model="mainView.x" /> {{x}}
    </div>
    <div ng-controller="MyCtrl">
      <input type="text" ng-model="mainView.x" /> {{x}}
    </div> 
  </body>

And JS:

function MainCtrl($scope) {
  $scope.mainView = {};
}
function MyCtrl($scope) {

}

We created a mainView object on the MainController, and since MyController and its scope prototypally inherit from MainController we can reach that.
There is one caveat you should be aware of, when you use ngModel, it is almost always best to have a dot in somewhere (paraphrased from angularjs's authors).

我们在MainController上创建了一个mainView对象,由于MyController及其范围原型继承自MainController,我们可以实现。有一点需要注意,当你使用ngModel时,几乎总是最好在某个地方有一个点(从angularjs的作者转述)。

Due to javascript's prototypal inheritance:

由于javascript的原型继承:

// In MainCtrl
$scope.mainView.x = "hello";
$scope.myX = "hello";

// In MyCtrl
$scope.mainView.x
>> "hello"
$scope.myX
>> "hello"
$scope.mainView.x = "welcome";
$scope.myX = "welcome";

// In MainCtrl
$scope.mainView.x
>> "welcome"
$scope.myX
>> "hello"

When you ask for a property in an object in javascript, it looks its properties to see if there is one, if not, it goes up in the prototype chain (parent), and looks for it there, it goes up until it finds any or goes at the end of the prototype chain.

当你在javascript中请求对象中的属性时,它会查看其属性以查看是否有一个属性,如果没有,它会在原型链(父级)中上升,并在那里查找它,它会一直上升,直到找到任何或者在原型链的末尾。

So when we set $scope.myX, we don't actually change myX in the parent scope but we create a property called myX in the current scope; because of the hiearchy in the prototype. However, when we set $scope.mainView.x, we first ask for mainView then set x which then results in changing the value in parent scope.

因此,当我们设置$ scope.myX时,我们实际上并没有更改父作用域中的myX,而是在当前作用域中创建了一个名为myX的属性;因为原型中的层次结构。但是,当我们设置$ scope.mainView.x时,我们首先要求mainView然后设置x然后导致更改父范围中的值。

I know it feels kind of unrelated to the original question but surely one would suffer from this when one goes into controller and scope inheritance.

我知道这与原始问题有点无关,但当进入控制器和范围继承时,肯定会受此影响。

#1


4  

To share data between controllers, normally a service is your best option. Put the shared data into the service, and inject the service into the controller:

要在控制器之间共享数据,通常服务是您的最佳选择。将共享数据放入服务,并将服务注入控制器:

function myController($scope, MyService) {

Each scope/controller instance will then be able to access the shared data.

然后,每个范围/控制器实例都可以访问共享数据。

Note that services are singletons, so there will only be one instance of your shared data around.

请注意,服务是单例,因此只有一个共享数据实例。

Here is a fiddle (I didn't write it) showing how two controllers can share data.

这是一个小提琴(我没写它),展示了两个控制器如何共享数据。

See also AngularJS: How can I pass variables between controllers? and
Angularjs: two way data bindings and controller reload.

另请参见AngularJS:如何在控制器之间传递变量?和Angularjs:双向数据绑定和控制器重新加载。

#2


3  

Ideally, you should have only one application running in a single page. Since you also need to communicate between the controllers, you should really run a single application. Possibly on body or html. Then you can create a main controller which would encapsulate all your controllers. (controller inheritance).

理想情况下,您应该只在一个页面中运行一个应用程序。由于您还需要在控制器之间进行通信,因此您应该真正运行单个应用程序。可能在身体或HTML上。然后,您可以创建一个主控制器,它将封装所有控制器。 (控制器继承)。

Here is what it should look like:

这是它应该是什么样子:

<html ng-app="myApp">
  <head>...</head>
  <body ng-controller="MainCtrl">
    <div ng-controller="MyCtrl">
      <input type="text" ng-model="mainView.x" /> {{x}}
    </div>
    <div ng-controller="MyCtrl">
      <input type="text" ng-model="mainView.x" /> {{x}}
    </div> 
  </body>

And JS:

function MainCtrl($scope) {
  $scope.mainView = {};
}
function MyCtrl($scope) {

}

We created a mainView object on the MainController, and since MyController and its scope prototypally inherit from MainController we can reach that.
There is one caveat you should be aware of, when you use ngModel, it is almost always best to have a dot in somewhere (paraphrased from angularjs's authors).

我们在MainController上创建了一个mainView对象,由于MyController及其范围原型继承自MainController,我们可以实现。有一点需要注意,当你使用ngModel时,几乎总是最好在某个地方有一个点(从angularjs的作者转述)。

Due to javascript's prototypal inheritance:

由于javascript的原型继承:

// In MainCtrl
$scope.mainView.x = "hello";
$scope.myX = "hello";

// In MyCtrl
$scope.mainView.x
>> "hello"
$scope.myX
>> "hello"
$scope.mainView.x = "welcome";
$scope.myX = "welcome";

// In MainCtrl
$scope.mainView.x
>> "welcome"
$scope.myX
>> "hello"

When you ask for a property in an object in javascript, it looks its properties to see if there is one, if not, it goes up in the prototype chain (parent), and looks for it there, it goes up until it finds any or goes at the end of the prototype chain.

当你在javascript中请求对象中的属性时,它会查看其属性以查看是否有一个属性,如果没有,它会在原型链(父级)中上升,并在那里查找它,它会一直上升,直到找到任何或者在原型链的末尾。

So when we set $scope.myX, we don't actually change myX in the parent scope but we create a property called myX in the current scope; because of the hiearchy in the prototype. However, when we set $scope.mainView.x, we first ask for mainView then set x which then results in changing the value in parent scope.

因此,当我们设置$ scope.myX时,我们实际上并没有更改父作用域中的myX,而是在当前作用域中创建了一个名为myX的属性;因为原型中的层次结构。但是,当我们设置$ scope.mainView.x时,我们首先要求mainView然后设置x然后导致更改父范围中的值。

I know it feels kind of unrelated to the original question but surely one would suffer from this when one goes into controller and scope inheritance.

我知道这与原始问题有点无关,但当进入控制器和范围继承时,肯定会受此影响。