通过ref将$ scope.property注入工厂实例

时间:2015-03-11 16:10:10

标签: javascript angularjs watch

我需要一个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。如果我在工厂外面,在控制器中这样做,我需要为每个实例执行此操作。我应该在工厂对象上设置某种寄存器方法吗?

是否有任何我可能想要使用的建议,模式或内容?

1 个答案:

答案 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>