我需要一个Factory对象,可以使用$ scope.property来获取结果。我还需要知道工厂实例中的修饰符或$ scope.property是否更改以更新结果。我当然看到这种模式可能是错的。
app.factory('MyFactory',
function () {
var MyFactory = function (name, modifier) {
this.name = name;
this.result = 0;
this.modifier = modifier;
}
//I might want to call this when modifier or MyProperty changes
MyFactory.prototype.modifyingMethod = function () {
this.result = this.modifier * //externalProperty;
}
MyFactory.prototype.watcher = function () {
//no idea what I will do here or if I need this at all
// I need to recalculate the result like with $watch
this.modifyingMethod();
}
return MyFactory;
}
)
app.controller('MyCtrl'
function($scope, MyFactory) {
$scope.MyProperty = 42;
$scope.MyFactoryOptions = [
new MyFactory('Option1', 1),
new MyFactory('Option2', 2),
new MyFactory('Option3', 3),
new MyFactory('Option4', 4),
new MyFactory('Option5', 5)
];
}
所以我有问题需要$ watch MyProperty和修饰符(可以更改用户),所以我可以更改结果。如果Property是一个将其传递给Factory构造函数的值类型将不起作用。也许我可以在返回MyProperty中传递一个函数。
我可以在工厂设置内部$ watch。如果我在工厂外面,在控制器中这样做,我需要为每个实例执行此操作。我应该在工厂对象上设置某种寄存器方法吗?
是否有任何我可能想要使用的建议,模式或内容?
答案 0 :(得分:1)
基本上你可以将你的工厂理解为对象集合的接口(数组或关联数组,分别是纯javascript对象)。
我发现你对物体的方法非常有吸引力,我相信你可以做到类似的事情。我仍然把小提琴放在一起,显示我将如何解决问题:
在 MVC 模式中,Factory将成为模型,控制器应尽可能简单,带指令的HTML代表视图。
您的控制器会监视用户的更改($scope.MyProperty
与$watch
)。虽然模型是自我意识到任何依赖外部属性的变化。请注意,ExternalObject
服务/工厂的更改只有在不是原始值的情况下才能识别。这就是为什么在ExternalObject
工厂我返回整个对象。
在完美的世界中,您不需要以间隔来监听更改,但会收到javascript事件。如果可以,那就去做吧!请注意,如果要查看视图中的更改,则Angular范围内的对象更新将需要您执行$scope.$apply()
。 $interval
和$timeout
都会调用$scope.apply()
,因此使用它们是最佳做法。
实际上,在此代码中仍然需要进行大量清理,但它可能会为您提供如何使用替代结构的基本知识:
var app = angular.module('yourApp', []);
window.yourGlobalObject = {};
setInterval(function () {
yourGlobalObject.externalProperty = Math.floor(Math.random() * 5000);
}, 1000);
app.factory('ExternalObject', ['$window', function ($window) {
return $window.yourGlobalObject;
}]);
app.factory('MyFactory', ['$interval', 'ExternalObject', function ($interval, ExternalObject) {
var options = [{
name: 'Option1',
modifier: 1
}, {
name: 'Option2',
modifier: 2
}, {
name: 'Option3',
modifier: 3
}],
cachedExternalProperty = 0,
cachedMyProperty = 0;
MyFactory = {
getOptions: function () {
return options;
},
addOption: function (name, modifier) {
options.push({
name: name,
modifier: modifier
});
},
setMyProperty: function (value) {
cachedMyProperty = value;
},
setResults: function (myProperty) {
angular.forEach(options, function (option, key) {
option.result = option.modifier * ExternalObject.externalProperty * myProperty;
});
console.log(options);
}
};
// let the service check for updates in the external property, if changed
$interval(function () {
if (cachedExternalProperty !== ExternalObject.externalProperty) {
cachedExternalProperty = ExternalObject.externalProperty;
MyFactory.setResults(cachedMyProperty);
}
}, 1000);
return MyFactory;
}]);
app.controller('MyCtrl', ['$scope', 'MyFactory', function ($scope, MyFactory) {
$scope.MyProperty = 42;
$scope.MyFactoryOptions = MyFactory.getOptions();
$scope.setResults = function () {
MyFactory.setResults($scope.MyProperty);
};
$scope.$watch('MyProperty', function (value) {
MyFactory.setMyProperty(value)
MyFactory.setResults(value);
});
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body>
<section ng-app="yourApp" ng-controller="MyCtrl">
<button ng-click="setResults(MyProperty)">Update Results</button>
<div ng-repeat="factory in MyFactoryOptions">{{factory.name}} {{factory.result}}</div>
<input type="number" ng-model="MyProperty">
</section>
</body>