Angularjs 是否可以在Angular 1中使用$rootScope作为存储实现类似Redux的体系结构?

Angularjs 是否可以在Angular 1中使用$rootScope作为存储实现类似Redux的体系结构?,angularjs,redux,flux,Angularjs,Redux,Flux,如果您使用的是大型遗留Angular 1代码库,并且不想引入新的依赖项(如ngRedux),那么开始使用经典Angular 1功能(如$rootScope、$broadcast、$on、$watch)来实现类似Redux的体系结构会是一个糟糕的主意吗 在我看来,可以按以下方式进行: 对于商店/模型->使用$rootScope 对于store.dispatch(ACTION)->使用$rootScope.$broadcast(ACTION) 还原器将被实现为服务注入$rootScope和执行$o

如果您使用的是大型遗留Angular 1代码库,并且不想引入新的依赖项(如ngRedux),那么开始使用经典Angular 1功能(如$rootScope、$broadcast、$on、$watch)来实现类似Redux的体系结构会是一个糟糕的主意吗

在我看来,可以按以下方式进行:

  • 对于商店/模型->使用
    $rootScope
  • 对于
    store.dispatch(ACTION)
    ->使用
    $rootScope.$broadcast(ACTION)
  • 还原器将被实现为服务注入
    $rootScope
    和执行
    $on(操作)
  • 控制器可以使用
    $watch
    监视
    $rootScope
    上的更改,并更新视图,或者视图可以直接绑定到
    $rootScope
    属性
只要你严格遵守纪律,不在
$rootScope
属性上进行奇怪的异地突变,将所有应用程序逻辑保留在减缩器中,并将控制器代码保持在最低限度,我所看到的最大缺点就是由于角度1昂贵的摘要周期而导致了糟糕的性能。但是,如果您也可以坚持使用不可变的数据结构,那么情况可能就不是这样了


这是个坏主意吗?有人试过吗?

当然,您可以只使用
$rootScope
完成您的任务。但是is还有很多其他的目的会干扰你的州

让我们看看:

// reducer-like
$rootScope.$on('COUNTER_INCREMENT', (e, action) => {
   //I don't use += to emphase immutability of count property;
   $rootScope.count = $rootScope.count + action.value;
});

//action-ish creator
$rootScope.$broadcast('COUNTER_INCREMENT', {value: 5});

//store subscribe-like
$rootScope.$watch('count', (count) => {
  //update something in your component
})
如果您愿意,您可以这样做,但是您看到了一个不明确的不变性问题。很难控制你的动作处理程序是纯的,因为它实际上不是

没有默认的操作处理程序,无法轻松设置存储的初始状态。您仍然使用
$watch
和摘要,这可能是您想要避免的

另外,你不能订阅所有的更新,没有一个像Redux那样对时间旅行的东西进行重置的单一点

如果您想继续使用Redux作为一种模式,那么您可能会得到一些帮助,使您的代码更像Redux

那么,为什么不从一个简单的angular utility服务开始使用Redux呢

angular.module('app', []).factory('store', () => {
  //if you have many reducers, they should be as separate modules, and imported here
  function counter(state = 0, action) {
    switch (action.type) {
      case 'INCREMENT':
        return state + action.value;
      default:
        return state;
    }
  }

  // here you can add here middlewares that make Redux so powerful
  return Redux.createStore(counter);
});
我们开始吧。现在,您可以使用商店服务执行操作

angular.module('app').controller('MyController', ($scope, store) => {
  store.subscribe(() => {
    //you may not to care about $scope.$digest, if your action was triggered within angular scope as well 
    $scope.count = store.getState();
  });

  $scope.onClick = () => store.dispatch({type: 'INCREMENT', value: 1});
});
现在您有了一个正确的设置,订阅者不知道由分派引起的操作,您的操作创建和操作减少逻辑完全独立,正如Redux模式所要求的那样