是否可以使用 $rootScope 作为存储在 Angular 1 中实现类似 Redux 的架构?
Posted
技术标签:
【中文标题】是否可以使用 $rootScope 作为存储在 Angular 1 中实现类似 Redux 的架构?【英文标题】:Is it possible to implement a Redux-like architecture in Angular 1 using $rootScope as the store? 【发布时间】:2016-08-01 17:15:23 【问题描述】:如果你在一个大型的遗留 Angular 1 代码库中并且你不想引入新的依赖项(如 ngRedux),那么开始使用经典的 Angular 1 特性(如 $rootScope、$broadcast)是不是一个糟糕的主意, $on, $watch 来实现类似 Redux 的架构?
在我看来,它可以做到以下几点:
对于商店/模型 -> 使用$rootScope
对于store.dispatch(ACTION)
-> 使用$rootScope.$broadcast(ACTION)
Reducer 将被实现为注入$rootScope
并执行$on(ACTION)
的服务
控制器可以使用$watch
监视$rootScope
上的更改并更新视图或视图可以直接绑定到$rootScope
属性
只要您遵守纪律,不要对 $rootScope
属性进行奇怪的异地突变,将所有应用程序逻辑保留在 Reducers 中并将控制器代码保持在最低限度,我能看到的最大缺点是由于 Angular 1 昂贵的摘要周期,性能很差。但是,如果您也可以坚持不可变数据结构,那可能就不是这样了。
这是个坏主意吗?有人试过吗?
【问题讨论】:
【参考方案1】:当然,您可以只使用$rootScope
来做您的事情。但是它还有很多其他的目的会干扰你的状态。
让我们看看:
// 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 实用程序服务开始使用 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 模式所要求的那样。
【讨论】:
以上是关于是否可以使用 $rootScope 作为存储在 Angular 1 中实现类似 Redux 的架构?的主要内容,如果未能解决你的问题,请参考以下文章