Модули AngularJS/совместное использование области видимости

Недавно я начал использовать AngularJS, и сейчас я создаю свои приложения следующим образом:

MainController.js

var app = angular.module('app', ['SomeController', 'MainController']);

app.controller('MainController', function ($scope) {
    // do some stuff
}

SomeController.js

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

SomeController.controller('SomeController', function ($scope) {
    $scope.variable = "test";
    // do some otherstuff
}

Проблема, с которой я сталкиваюсь, заключается в том, что область действия не распределяется между модулями. Например, из MainController я не могу получить переменную "test".

  • Какова наилучшая практика для этого? Хранить ли все свои контроллеры в 1 модуле в 1 файле?
  • Как я могу иметь 1 страницу с 2 контроллерами и разделить $scope между ними, или можно поместить все только в один контроллер?

person Chancho    schedule 23.12.2013    source источник
comment
Это определенно проблема X/Y. Если вам нужно сделать что-то подобное, вы делаете что-то очень неправильное. Обновите свой ответ, чтобы объяснить, чего вы на самом деле пытаетесь достичь.   -  person m59    schedule 24.12.2013
comment
В основном я спрашиваю, как мне это сделать, мне не обязательно делать это так.   -  person Chancho    schedule 24.12.2013
comment
Смотрите мой ответ, просто убедитесь, что вы упаковываете вещи, которые должны быть вместе, а не соединяете вещи, которые не должны быть связаны.   -  person m59    schedule 24.12.2013


Ответы (2)


Вы можете использовать такую ​​услугу: Живое демо здесь (нажмите).

JavaScript:

var otherApp = angular.module('otherApp', []);
otherApp.factory('myService', function() {
  var myService = {
    someData: ''
  };
  return myService;
});
otherApp.controller('otherCtrl', function($scope, myService) {
  $scope.shared = myService;
});


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

app.controller('myCtrl', function($scope, myService) {
  $scope.shared = myService; 
});

Разметка:

  <div ng-controller="otherCtrl">
    <input ng-model="shared.someData" placeholder="Type here..">
  </div>
  <div ng-controller="myCtrl">
  {{shared.someData}}
  </div>

Вот хорошая статья об обмене данными со службами.

Вы также можете вложить контроллеры, чтобы свойства области родительского контроллера наследовались дочерней областью: http://jsbin.com/AgAYIVE/3/edit

  <div ng-controller="ctrl1">
    <span>ctrl1:</span>
    <input ng-model="foo" placeholder="Type here..">
    <div ng-controller="ctrl2">
      <span>ctrl2:</span>
      {{foo}}
    </div>
  </div>

Но потомок не будет обновлять родителя — только свойства родителя обновляют дочерний элемент.

Вы должны использовать «точечное правило», чтобы обновления дочернего элемента влияли на родителя. Это означает вложение ваших свойств в объект. Поскольку у родительского и дочернего объектов один и тот же объект, изменения в этом объекте будут отражены в обоих местах. Именно так работают ссылки на объекты. Многие люди считают лучшей практикой не использовать наследование, а помещать все в директивы с изолированной областью действия.

person m59    schedule 23.12.2013
comment
Спасибо за объяснение, это обычная практика - иметь несколько модулей на 1 странице / или частично, я должен сказать? у меня есть идея, что я делаю это неправильно. - person Chancho; 24.12.2013
comment
@Chancho Вы не используете несколько модулей (и не должны). Вы используете один модуль, который зависит от другого модуля. Такая связь хороша, но кажется, что вы думаете об этом неправильно. Предположим, что Module A — это своего рода созданный вами набор инструментов. Возможно, в нем есть служба, каталог и контроллер, которые работают вместе, чтобы обеспечить хорошую функциональность. Теперь вы создаете приложение, поэтому вы делаете Module B. Вы решаете, что Module B может использовать ту функциональность, которую вы создали и упаковали в Module A, поэтому Module B будет зависеть от Module A. - person m59; 24.12.2013
comment
хорошо, я думаю, теперь я это понял, но как насчет контроллеров, которые находятся в модулях. в основном, что я делаю сейчас, это создаю модуль с контроллером внутри. затем в другом контроллере я добавляю модуль в качестве зависимости от этого модуля. Я думаю, что здесь я иду неправильным путем. - поэтому, чтобы перефразировать мой вопрос: как мне связать несколько контроллеров с их областью вместе? - person Chancho; 24.12.2013
comment
@Chancho Скорее всего, вам действительно нужно сервисное решение, как я уже сказал. Это связывает эти области вместе, потому что они оба ссылаются на один и тот же объект. В противном случае их область наследования ограничена. jsbin.com/AgAYIVE/3/edit - person m59; 24.12.2013
comment
Если я просто хочу получить одно значение из другого контроллера, нужно ли мне создавать для этого службу? - person Chancho; 24.12.2013
comment
@ Чанчо Да. Имейте в виду общую картину — контроллер не должен заботиться о том, что делается с данными. Контроллер — это просто концентратор для данных в/из представления. Имея это в виду, задача контроллера здесь состоит в том, чтобы связать данные из представления с данными в службе. Затем что-то еще, зависящее от этой службы, может что-то сделать с ней. Если вы поняли концепцию, вы должны увидеть, что существует проблема с тем, что использует эти данные в зависимости от контроллера. - person m59; 24.12.2013
comment
лучший способ для вашего примера - использовать службу, потому что они одноэлементные (просто экземпляр), поэтому, когда вы обновите $scope.shared.someData (не имеет значения, каким контроллером), другие также увидят обновление. это потому, что у них есть ссылка на один и тот же объект экземпляра. - person Giovanni Far; 27.03.2016

Вы можете использовать $rootScope, каждое приложение Angular имеет ровно одну корневую область.

Справочник

app.controller('MainController', function ($scope, $rootScope) {
    $rootScope.data = 'App scope data';
}
person Steely Wing    schedule 13.08.2014
comment
Каждый модуль имеет свой собственный $rootScope. - person Dan Ochiana; 15.10.2014
comment
Даже если бы вы могли получить доступ к такому глобальному объекту и поделиться состоянием — это известно как Common Coupling и его уровень «Нет-нет» 4 из 5 (Связь контента является самой высокой). #badPractice, #tightCoupling, #theBadTypeOfComplexity . - person Cody; 13.12.2014
comment
Мммм ... Я использую Angular 1.5.5, и каждый модуль, конечно, НЕ получает свой собственный $ rootScope. - person Wrecks; 30.04.2016
comment
Наверняка есть одна $rootScope, или она должна быть, если только вы не делаете что-то не так, например, передаете ее между модулями или где-то присваиваете другой переменной. Я не вижу в вопросе OP ничего, что указывало бы на то, что переменная может не быть переменной static (что было бы полностью подходящим для $rootScope и позволяет избежать сложности службы). - person Chris Halcrow; 07.04.2017