Javascript AngularJS-哪一个更好,$emit/$on还是作用域继承?

Javascript AngularJS-哪一个更好,$emit/$on还是作用域继承?,javascript,inheritance,angularjs,architecture,prototypal-inheritance,Javascript,Inheritance,Angularjs,Architecture,Prototypal Inheritance,假设我得到以下HTML结构: <body ng-app="demo" ng-controller="RootCtrl"> <header> <!-- Header Material --> </header> <main ng-controller="MainCtrl"> <!-- Main Content --> <nav ng-contro

假设我得到以下HTML结构:

<body ng-app="demo" ng-controller="RootCtrl">
    <header>
        <!-- Header Material -->
    </header>

    <main ng-controller="MainCtrl">
        <!-- Main Content -->

        <nav ng-controller="NavCtrl">
            <!-- Navbar -->
        </nav>
    </main>
<body>


现在,假设
NavCtrl
需要操作一个恰好存在于
RootCtrl
作用域下的模型-在什么条件下
$emit/$on
更合适?在什么情况下,通过作用域继承直接操作模型更好?

如果使用原型继承,则需要小心,因为在父控制器和子控制器中使用相同的变量名时很容易出错。这可以通过确保$scope变量始终在某个地方“有一个点”来避免,但需要遵守规则以确保始终这样做。您还可以使用
$scope.$parent.$parent
结构访问RootCtrl中NavCtrl集合中的变量,但这很脆弱,本质上会将您的控制器与DOM结构绑定在一起,而DOM结构会导致问题

$emit/$on如果在事件名称中输入了错误,则可能会出现静默失败的问题,并且在发生错误时很难了解发生了什么。最好少用。“当您需要让多个订阅者了解某个事件,而这些订阅者需要做的不仅仅是将信息辐射到他们的视图中时”才使用它们

跨控制器共享数据模型的正常方式是创建一个服务,并将其注入两个控制器。这通常也符合OOP的“”原则

app.service('dayService', function () {      
    var day = 'Monday';
    return {
        getDay: function() {
           return day;
        },
        setDay: function(thisDay) {
           day = thisDay;
        }
    };
})

function NavCtrl($scope, dayService) {
    $scope.day = dayService.getDay();
}

function RootCtrl($scope, dayService) {
    dayService.setDay('Sunday');
}
HTML:


今天是{day}
你可能也会发现Misko很有趣,它讨论了在28分钟左右控制器和服务中应该放些什么,以及更多关于最后的事件($emit/$on)。他的结论(意译)是,事件在某种程度上是有问题的,最好只用于两件事情确实不需要相互了解并且必须非常分开的情况,或者如果事件并非总是必要的,有时可以忽略

我要说的基本规则是:

  • 使用服务在两个控制器之间共享数据,这比继承稍微复杂一些,但并不太困难

  • 使用事件在多个不同订阅者之间以复杂的方式共享

  • 控制器中的$scope应为“只写”(规则直接取自上面Misko的最佳实践视频)。“NavCtrl需要操作恰好存在于RootCtrl作用域下的模型”的作用域继承也需要读取父作用域,所以我认为最好避免


如果RootCtrl中的模型是一个对象,而NavCtrl只需要修改模型对象的几个属性,那么使用范围继承将是最简单的。如果您想采用这种方法,只需确保您知道原型是如何工作的

正如mikel在回答中提到的,使用服务在控制器之间共享数据是可行的,但对于简单的情况,它的设置是相当过分的,尤其是当范围继承对您可用时。而且,该服务将存在于你的应用程序的整个生命周期中,这可能不是你想要或需要的

IMHO,$emit/$on在您的情况下工作得相当好。设置不太繁重,作用域被很好地解耦,对模型的所有修改都集中在RootCtrl中,我认为这对维护很有好处。如果您担心键入事件名称时可能出现的错误,可以使用
模块.constant()
为事件名称创建常量,然后使用这些常量,而不是一直以字符串形式键入事件名称

<nav ng-controller="NavCtrl">
    Today is {{day}}
</nav>