AngularJS 使用 $broadcast 帮助在控制器之间共享数据

AngularJS help sharing data between controllers using $broadcast

我一直在尝试使用 $broadcast 和 $on,但我就是无法让数据在两个控制器之间移动。

在我的主网页上,我有一个按钮,每次点击它都会将 4 添加到 var:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body ng-app="app">
    <div ng-controller="mainCtrl">

        <button ng-click="add(4)"> 4 </button>

    </div>
    <script src="../Scripts/angular.js"></script>
    <script src="../assets/js/angular-grid.js"></script>
    <script src="../assets/controller/gods_controller.js"></script>
    <script src="../Scripts/angular-animate.js"></script>
</body>
</html>

在我的 mainCtrl 中,我有函数 add() 并使用 $broadcast 广播我的值:

var module = angular.module("app", ["angularGrid", "ngAnimate"])

module.controller("mainCtrl", function ($scope, $rootScope) {

var total = 0

    $scope.add = function (x) {
        total += x;

        $rootScope.$broadcast('totalBroadcast', total)

    }

});

然后我有第二个控制器用于我的弹出窗口,使用 $on 接收广播:

module.controller('popUpCtrl', function ($scope) {


     $scope.$on('totalBroadcast', function(events, args){

  $scope.total = args;
  })

   })

然后我的弹出窗口 HTML 使用第二个控制器和 $scope.total 作为表达式:

    <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body ng-app="app">
    <div ng-controller="popUpCtrl">

       <p>The total is: {{total}}</p>

    </div>
    <script src="../Scripts/angular.js"></script>
    <script src="../assets/js/angular-grid.js"></script>
    <script src="../assets/controller/gods_controller.js"></script>
    <script src="../Scripts/angular-animate.js"></script>
</body>
</html>

似乎没有数据传递到我的第二个控制器,表达式根本没有显示任何内容。

编辑


我也尝试过使用服务,HTML上面的保持不变,但现在我添加了服务

module.factory('myService', function () {

    var total = 0;

    var setTotal = function (x) {
        total = x;
    }

    var getTotal = function () {
        return total;
    };

    return {
        setTotal: setTotal,
        getTotal: getTotal
    }


    });

我的主控制器和广告功能现在是:

 module.controller("mainCtrl", function ($scope, myService) {

    var total = 0

    $scope.add = function (x) {

        myService.setTotal(x)
    }

 });

我的 popupCtrl 控制器现在是这样的:

module.controller('popUpCtrl', function ($scope, myService) {


    $scope.total = myService.getTotal();

})

{{total}} 在我的弹出窗口中现在表示为“0”,它在我的服务中等于 var total。因此,现在正在使用该服务传输数据,但 setTotal() 方法现在并未按照 add() 函数的指示设置 var。我已将我的服务作为两个控制器的依赖项注入。

添加监视或广播以在控制器之间共享数据是一种非常糟糕的做法,这样做是为了在两个控制器中注入公共服务。

Services provide an easy way for us to share data and functionality throughout our app. The services we create are singletons that can be injected into controllers and other services, making them the ideal place for writing reusable code.

关注其linkhttps://thinkster.io/a-better-way-to-learn-angularjs/services

您得到零的原因是您的控制器仅在加载时才分配给 myService.getTotal() 的值。这意味着当您更改 total 变量时,它不会更新。

您需要 $watch 更新:

$scope.$watch(function () {
    return myService.getTotal();
}, function (newVal) {
    $scope.total = newVal;
});

此外,您似乎正在使用新页面重新初始化您的应用。这不是 angular 的工作方式。阅读有关 angular route 的信息,然后尝试执行我在此处建议的操作。如果你把它做成一个单页应用程序,它应该可以工作。

我确实找到了解决我最初问题的方法,即使用 localStorage.setItem("num", "num") 将数据存储在浏览器中。这似乎是专门为在 tabs/windows 之间共享数据而开发的,因此可以通过 localStorage.getItem("num").

访问

这回答了我最初的问题,但我现在希望 total 能够动态更新。目前它仅在刷新时更新。任何提示将不胜感激。


编辑(对上述问题的回答)

通过在我的第二个弹出窗口中使用此事件侦听器 -

window.addEventListener('storage', function (event) {
        $scope.total = parseInt(event.newValue);
        $scope.$apply();
    });

我能够访问存储并将其绑定到我 HTML 中的表达式。请记住 $scope.apply() 需要在这里调用,因为总计超出范围。

此处有更多详细信息 - https://developer.apple.com/library/safari/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/Name-ValueStorage/Name-ValueStorage.html