2017-01-25 22 views
2

Как рекомендовал Angular team (и несколько цифр blogs), я стараюсь избегать использования $rootScope, насколько это возможно в моих приложениях.

$rootScope существует, но он может быть использован для зла

«Конечно, глобальное состояние отстой, и вы должны использовать $rootScope экономно, , как вы бы (надеюсь) использовать глобальные переменные в любом языке В частности, не используйте его для кода, только данные. Если у вас есть соблазн , поместите функцию на $rootScope, почти всегда лучше поместить ее в службу , которую можно вставить туда, где это необходимо, и многое другое легко проверено. " - от Angular FAQ

Но в одном из моих приложений, я использую несколько раз такие события, как $routeChangeStart, которые широковещательные события с помощью $rootScope:

/* Force redirection to home page when a connected user calls login page */ 
$rootScope.$on("$routeChangeStart", function(event, next, current) { 
    if(next.$$route.originalPath == '/login' && Session.isUserConnected()) { 
     $location.path("/home"); 
    } 
} 

Я не вижу способ избегайте $rootScope в этих случаях.

  • Есть ли более элегантный способ делать подобные трюки?
  • Является ли это ошибкой дизайна моего приложения, чтобы использовать его?
  • Должен ли я смириться с тем, чтобы использовать его, когда это абсолютно необходимо?

Скажите мне, если вы хотите, чтобы я предоставить больше примеров кода.

+0

Вы читали это «глобальное состояние отстойно, и вы должны использовать $ rootScope экономно» ??? –

+0

@RameshRajendran Да, из [первой ссылки] (https://docs.angularjs.org/misc/faq) я предоставил (последний абзац). Это из ** Угловой документации FAQ **. – Mistalis

+0

для этого случая вы просто слушаете событие, транслируемое в $ rootScope, я думаю, что это допустимый прецедент. – Icycool

ответ

0

Вы missread что. Прежде всего, это событие было добавлено командой Angular - как вы думаете, они рекомендуют не использовать ее? D В этой статье вы не должны ставить все на $ rootScope, что, по-видимому, является легким для новичков.

На самом деле, используя $rootScope - для глобальных событий абсолютно нормально - это фактическая цель этой услуги.

+0

Интересно, есть ли «хорошие практики» о том, как структурировать этот код (как это делается на $ rootScope, вы можете написать его везде), чтобы он оставался настолько ясным и максимально читаемым, как можно – Mistalis

+0

«глобальные вещи, которые всегда верно ", должно быть в app.run(). - (потому что он всегда будет выполняться в вашем приложении init) –

1

Если вы не хотите использовать $rootScope в этом сценарии yyou можно достичь этого с помощью мощного resolve.

Поскольку я видел, что вы используете модуль ngRoute, я создал Plunker и код для ngRoute. Я могу создать его для ui-router, если вы этого хотите.

Использование Resolve делает код выполняется быстрее, так как он не будет подвергаться DigestCycle

Вы можете получить флаг пользователя из Session.isUserConnected() путем инъекции сессии.

Затем вы можете использовать эту переменную для перенаправления маршрута.

// Code goes here 
 

 
angular.module('Test', ['ngRoute']) 
 
.config(function($routeProvider) { 
 
    var user = true; 
 
    //var user = Session.isUserConnected(); You can use your logic here 
 
    $routeProvider 
 
    .when("/login", { 
 
     template: "Login View", 
 
     resolve: { 
 
      
 
     data: function($q, $timeout,$location) { 
 
      var deferred = $q.defer(); 
 
      $timeout(function() { 
 
       
 
       if (user) { 
 
       $location.path("/home"); 
 
       deferred.reject(); 
 
       } else { 
 
       deferred.resolve(); 
 
       } 
 
      }); 
 
    
 
      return deferred.promise; 
 
      } 
 
     } 
 
    }) 
 
    .when("/home", { 
 
     template: "Home View. It is redirected from Login by checking the user condition. Without using the rootscope", 
 
     }) 
 
    .otherwise({redirectTo:'/login'}); 
 
}) 
 

 
    
 
<!DOCTYPE html> 
 
<html ng-app="Test"> 
 
    <head> 
 
    <link rel="stylesheet" href="style.css" /> 
 
    </head> 
 
    
 
    <body> 
 
    <div ng-view></div> 
 
    
 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script> 
 
    <script src="http://angular-ui.github.io/ui-router/release/angular-ui-router.js"></script> 
 
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-route.js"></script> 
 
    </body> 
 
</html>

Основная часть идет здесь:

data: function($q, $timeout, $location) { 
    var deferred = $q.defer(); 
    $timeout(function() { 
     if (user) { 
      $location.path("/home"); 
      deferred.reject(); 
     } else { 
      deferred.resolve(); 
     } 
    }); 
    return deferred.promise; 
} 

HERE IS A WORKING DEMO

+0

Интересная точка зрения. Что касается производительности и дизайна, это лучше, чем использование '$ rootScope'? Думаете ли вы, что я ** должен использовать его или это только предложение «как поступать по-другому»? – Mistalis

+0

Поскольку изменение '$ rootScope' снова запускает цикл дайджеста и разрешает выполнение только один раз при вызове маршрута, разрешение может быть лучше по сравнению с' $ routeScope', также, как вы просили, это альтернатива ' $ rootScope'. – Sravan

+0

@Mistalis, этот ответ решил вашу проблему? – Sravan