AngularJS - $emit/$on 和作用域继承哪个更好?

5

假设我有以下的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更合适?在哪些情况下直接通过作用域继承操作模型更合适?

2个回答

7
如果您正在使用原型继承,需要小心,因为在父控制器和子控制器中使用相同的变量名很容易出错。这可以通过确保$scope变量始终在某个地方“有一个点”来避免,但需要纪律性以确保您始终这样做。您还可以使用$scope.$parent.$parent结构访问在RootCtrl中设置的NavCtrl变量,但这很脆弱,并且基本上将您的控制器与DOM结构绑定在一起,这将导致问题。 $emit/$on存在潜在的问题,如果您在事件名称中拼写错误,则可能会默默失败,并且在出现错误时很难跟踪发生了什么。最好节俭使用它们。http://eburley.github.io/2013/01/31/angularjs-watch-pub-sub-best-practices.html建议仅在“需要让多个订阅者知道事件并且这些订阅者需要执行更多操作而不仅仅是向其视图辐射信息”时使用它们。

在Angular中,共享数据模型的常规方法是创建一个服务,并将其注入到两个控制器中。这符合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:

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

你可能会发现Misko关于Angular最佳实践的视频很有趣,它讲述了在控制器和服务之间放置什么内容,大约在28分钟的时候,以及更多关于事件($emit/$on)的内容。他的结论是(引用):事件有些问题,最好只在两个事物真正不需要相互了解和必须保持非常独立的情况下使用,或者如果事件并不总是必要的,有时可以忽略。

我认为基本规则如下:

  • 在两个控制器之间共享数据时,请使用服务,它比继承略微复杂,但并不难。

  • 在复杂的方式中,在多个不同的订阅者之间共享数据时,请使用事件。

  • 在控制器中使用$scope应该是“只写”的(直接从Misko的最佳实践视频中取得的规则)。当“NavCtrl需要操作存在于RootCtrl范围下的模型”时,作用域继承将涉及读取父作用域,因此我认为最好避免。


1
如果RootCtrl中的模型是一个对象,并且NavCtrl只需要修改模型对象的几个属性,则使用作用域继承将是最简单的方法。只需确保您知道原型如何工作,如果您想采用这种方法。
使用服务在控制器之间共享数据是可行的,正如mikel的答案中所提到的,但对于简单情况来说,它的设置过于繁琐,特别是当作用域继承可用时。而且,该服务将存在于应用程序的整个生命周期中,这可能不是您想要或需要的。
在我看来,在您的情况下$emit/$on效果相当不错。设置并不太重,作用域很好地解耦,并且所有对模型的修改都集中在RootCtrl中,这对于维护是有好处的。如果您担心在键入事件名称时可能会犯错误,可以通过使用module.constant()创建事件名称的常量,然后始终使用这些常量而不是字符串键入事件名称。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接