使用ControllerAs语法绑定服务变量,不带$scope

Binding with service variable using ControllerAs syntax without $scope?

本文关键字:不带 scope 变量 服务 ControllerAs 语法 绑定 使用      更新时间:2023-09-26

我正在熟悉AngularJS中的controllerAs语法,当我需要对服务变量做一个简单的绑定时,我遇到了一个问题。通常$scope.$watch$scope.$on就可以了,但这需要注入$scope,这似乎破坏了控制器的目的。

目前我所拥有的是,点击其中一个按钮并调用config.setAttribute(attr)后,控制器调用服务的setAttribute函数,但不是getAttribute,所以config.attribute永远不会改变。

我在处理这件事的过程中是否忽略了什么?我是否需要注入$scope或更改控制器语法以使用$scope代替?

视图:

<div data-ng-controller="ConfigCtrl as config">
    <h3>Customize</h3>
    <pre>Current attribute: {{config.attribute}}</pre>
    <label>Attributes</label>
    <div data-ng-repeat="attr in config.attributes">
        <button ng-click="config.setAttribute(attr)">{{attr.name}}</button>
    </div>
</div>

服务:

(function() {
'use strict';
angular.module('app')
.factory('Customization', Customization);
function Customization() {
    var service = {
        attribute: null,
        getAttributes: getAttributes,
        setAttribute: setAttribute,
        getAttribute: getAttribute
    }
    return service;
    /////
    function getAttributes() {
        return [
            {name: 'Attr1', value: '1'},
            {name: 'Attr2', value: '2'} // etc.
        ];
    }
    function setAttribute(attr) {
        service.attribute = attr;
    }
    function getAttribute() {
        return service.attribute;
    }
}})();

控制器:

(function(){
'use strict';
angular.module('app')
.controller('ConfigCtrl', ConfigCtrl);
function ConfigCtrl(Customization){
    var vm = this;
    vm.attribute = Customization.getAttribute(); // bind
    vm.attributes = [];
    // Functions
    vm.setAttribute = Customization.setAttribute;
    init();
    /////
    function init(){
        // Get attributes array
        vm.attributes = Customization.getAttributes();
    }
}})();

在注入$scope并添加attribute的手表后,我的控制器看起来像:

(function(){
'use strict';
angular.module('app')
.controller('ConfigCtrl', ConfigCtrl);
function ConfigCtrl($scope, Customization){
    var vm = this;
    vm.attribute;
    vm.attributes = [];
    // Functions
    vm.setAttribute = Customization.setAttribute;
    init();
    /////
    function init(){
        // Get attributes array
        vm.attributes = Customization.getAttributes();
    }
    $scope.$watch(function() {
        return Customization.getAttribute()
    }, function() {
        vm.attribute = Customization.getAttribute();
    });
}})();

我也有业力测试,以防有人感兴趣:

(function() {
    'use strict';
    describe('ConfigCtrl', function () {
        var ConfigCtrl, scope;
        beforeEach(module('app'));
        beforeEach(inject(function($rootScope, $controller) {
            scope = $rootScope.$new();
            ConfigCtrl = $controller('ConfigCtrl',
                {$scope: scope}
            );
        }));
        describe('#setAttribute', function(){
            it('sets the current attribute', function(){
                var selected = {
                    name:'Attr1',
                    value:'1'
                };
                ConfigCtrl.setAttribute(selected);
                scope.$apply();
                expect(ConfigCtrl.attribute).to.eql(selected);
            });
        });
    });
})();

谢谢你的帮助。如果有人有更好的答案,我欢迎。