想象一下,我有一个控制器,可以处理,例如,视图更改:
function Controller($scope){ var viewmodel = this; viewmodel.goBack= function(){ viewmodel.visible = visibleLinks.pop(); //get last visible link viewmodel.swipeDirection = 'left';// for view change animation } }
但是我想要处理它不仅仅是例如在< body>里面的HTML按钮,还有设备上的Back按钮.所以我必须为deviceready事件添加事件监听器,并且还显式调用$scope.$apply()以便在AngularJS上下文之外调用它,如下所示:
document.addEventListener("deviceready",function(){ document.addEventListener("backbutton",function(){ viewmodel.goBack(); $scope.$apply(); },false); },false); }
但是我也想跟随(相对:)新的控制器算法,因为现在推荐这样做,例如作者:Todd Motto:Opinionated AngularJS styleguide for teams,它允许在不使用$emit或$on之类的东西时从控制器中删除$scope.但我不能这样做,我必须调用$apply()因为当用户点击设备后退按钮时我的上下文不是Angular上下文.我想创建一个服务,它可以作为cordova的包装外观,并为此服务注入$scope,但正如我在这里读到的那样:Injecting $scope into an angular service function()是不可能的.我看到了这个:Angular JS & Phonegap back button event并且接受的解决方案还包含$apply(),这使得$scope无法移除.任何人都知道在Angular控制器之外删除Cordova特定事件的解决方案,以便在不需要表达时从控制器中删除$scope?先感谢您.
解决方法
我没有看到为什么要从控制器中删除$scope的原因.如果不需要,可以按照最佳做法并删除它,但正如你所说,你仍然需要$emit,$on,$watch ..你可以在列表中添加$apply()肯定.
我在这里建议作为替代解决方案是实现一个将处理它的辅助函数.我们可以将它放在一个服务中并使用可注入的$rootScope服务.
app.factory('utilService',function ($rootScope) { return { justApply: function () { $rootScope.$apply(); },createNgAware: function (fnCallback) { return function () { fnCallback.apply(this,arguments); $rootScope.$apply(); }; } }; }); // use it app.controller('SampleCtrl',function(utilService) { var backBtnHandler1 = function () { viewmodel.goBack(); utilService.justApply(); // instead of $scope.$apply(); } // or var backBtnHandler2 = utilService.createNgAware(function(){ viewmodel.goBack(); }); document.addEventListener("backbutton",backBtnHandler2,false); });