【问题标题】:Alternate way to access AngularJS isolated scope访问 AngularJS 隔离范围的替代方法
【发布时间】:2014-07-20 01:28:08
【问题描述】:

AngularJS 隔离作用域是在 Angular 指令中创建可重用组件的好方法。我非常喜欢它。有时需要访问子作用域来操作数据或调用方法。要做到这一点,角度给了我们两个选择,

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

scope: {
    someObject: '='
},

(2) 来自 DOM 元素的 scope().$$childHead。 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'});
}]);

HTML

<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(){};
        })
    };
});

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

请让我知道您的诚实意见,或提出更好的方法。

【问题讨论】:

  • 你想做什么?什么不工作?
  • 没有什么是错的,除了以下几点:1.我是AngularJS的新手,2.我想要完全访问隔离范围。这就是我使用该类 LinkController 的原因。只需要知道我是否走错了方向。
  • 这个概念毫无意义。使用像scope().$$childHead 这样的东西是非常不寻常的。您对 Angular 工作原理的基本理解似乎缺少一些东西
  • 如果它根本不是“孤立的”,那么称它为“孤立的”范围有什么意义?要么为指令维护一个独立的范围,要么不从父级继承。两者之间没有任何东西。请参阅有关 Understanding Scope 的精彩页面。
  • 感谢您提供这些资源。

标签: javascript angularjs


【解决方案1】:

我相信隔离作用域的意义在于将作用域与其他一切分开,分离关注点。你真的应该通过提供绑定到控制器的对象或通过事件系统来接口你的指令。换句话说,你的控制器不应该知道任何关于你的指令内部的明确信息。

我想不出你需要从控制器访问整个指令范围的充分理由。

【讨论】:

  • 因为想少写代码,所以去掉父子之间的绑定。然后让我们将其视为第 4 种指令作用域,它可以选择带有公共 getter 的隔离作用域。
  • 我建议写一个新问题,概述您通过使范围可访问来实现的目标。我相信有一种简洁的方法可以得到你想要的结果,同时坚持模块化原则。
  • @Matt 我明白你的意思。我的解决方案工作得很好。但我把它贴在这里是为了吸引像你这样的优秀 Angular 专家的目光。根据您在这里的 cmets,我可能会删除我的解决方案并开始使用标准角度方式:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多