访问AngularJS隔离作用域的另一种方式

Alternate way to access AngularJS isolated scope

本文关键字:另一种 方式 作用域 AngularJS 隔离 访问      更新时间:2023-09-26

AngularJS隔离作用域是在angular指令中创建可重用组件的好方法。我非常喜欢它。有时需要访问子作用域来操作数据或调用方法。为此,angular给了我们两个选项:

(1)使用带有属性绑定的隔离作用域。像

scope: {
    someObject: '='
},

(2)从DOM元素的作用域()。Angular官方文档并不保证$$childHead会提供实际的子作用域。有时有效,有时无效。

scope().$$childHead

第一个选项的问题是它给了我们只使用绑定对象/数据的选项,而不是给我们对作用域的完整访问。也许这就是Angular想要做的,但我想要完全访问隔离作用域以及它的隔离特性。为了做到这一点,我创建了以下代码(在指令链接函数中,我使用了new LinkControl(function(scope, element, attr)){…}):

function LinkController(callback){
    var self = this;
    self.callback = callback;
    return function(scope, element, attr){
        LinkController._retainScope(scope, element, attr);
        self.callback.apply(this, arguments);
    }
}
LinkController._scopes = {};
LinkController.get = function(scopeId) {
    return LinkController._scopes[scopeId];
};
LinkController._retainScope = function(scope, element, attr){
    if (typeof(attr) === 'undefined') return;
    if (typeof(attr.scopeId) === 'undefined') return;
    var scopeId = attr.scopeId;
    LinkController._scopes[scopeId] = {
        scope: scope,
        element: element,
        attr: attr
    };
    if (typeof(element) != 'undefined') {
        element.on('$destroy', function(){ LinkController._releaseScope(scopeId); });
    }
};
LinkController._releaseScope = function(scopeId){
    delete LinkController._scopes[scopeId];
};

用法:

父控制器

app.controller('MainController', ['$scope', function($scope){
    var parentData = [1, 2, 3, 4];
    var anotherValue1 = LinkController.get('td01').attr.anotherValue || 'default value';
    var anotherValue3 = LinkController.get('td03').attr.anotherValue || 'default value';
    LinkController.get('td01').scope.data = parentData;
    LinkController.get('td02').scope.showNext();
    LinkController.get('td03').element.css({opacity: '.5'});
}]);

<test-directive scope-id="td01" any-attr="hello world" />
<test-directive scope-id="td02" any-attr="foo bar" />
<test-directive scope-id="td03" any-attr="alibaba" another-value="test value" />

指令

app.directive('testDirective', function(){
    return {
        restrict: 'EA',
        scope: {},
        templateUrl: '/url/to/file.html',
        link: new LinkController(function(scope, element, attr){
            scope.data = {};
            scope.showNext = function(){};
            scope.showPrevious = function(){};
        })
    };
});

它是内存安全的,因为它正确地释放了作用域指针。

请告诉我你的真实意见,或者建议更好的方法。

我认为隔离的作用域的意义在于保持作用域与其他所有东西分离,分离关注点。你应该通过提供绑定到控制器的对象,或者通过事件系统来接口你的指令。换句话说,你的控制器不应该知道任何关于指令内部的显式信息。

我想不出一个好的理由,你需要访问整个指令范围从一个控制器