【问题标题】:How to get transcluded element's scope to be the same as/inherit from isolate scope如何使嵌入元素的范围与隔离范围相同/继承
【发布时间】:2015-05-01 14:01:02
【问题描述】:

我有一个navbar 指令和collapseIcon 指令。我正在使用 angularJS 1.2.1。 collapseIcon 指令是 navbar. 内的子元素

<navbar>
    <collapse-icon></collapse-icon>
</navbar>

navbar 指令有一个带有 toggle() 函数的隔离作用域,我希望 collapseIcon's 作用域原型(?)从隔离作用域继承。为此,我阅读了在prelink() 函数中使用“transclude”函数(我在下面称之为链接器)。

我做了很多console.log() 语句,我最初看到collapseIcon 的范围与navbar 的范围相同,但由于某种原因它变回了。

这里是 js 小提琴:https://jsfiddle.net/67cgam3h/1/

代码如下:

app.directive('navbar', function () {
    return {
        transclude: true,
        require:"navbar",
        replace: true,
        restrict: 'E',
        scope: {
        },
        template: '<div class="navbar" ng-transclude></div>',
        controller: function ($scope) {
            this.expanded = false;
            var that = this;
            $scope.toggle = function () {
                if (that.expanded) {
                    $scope.contract();
                } else {
                    $scope.expand();
                }                
            }
        },
        link : {
            pre: function (scope, element, attrs, navbarCtrl, linker) {
                scope.expand = function () {
                    var height = element.prop('scrollHeight');
                    element.css('height', height + "px");
                    navbarCtrl.expanded = true;
                }
                scope.contract = function () {
                    element.css('height', '42px'); // hard-coded default height
                    navbarCtrl.expanded = false;
                }
                console.log('navbar scope');
                console.log(scope);
                console.log('navbar linking');
                linker(scope, function(clone) { // set the transcluded element's scope
                    console.log('appending navbar elements');
                    element.append(clone);
                });
            }
        }
    }
});

app.directive('collapseIcon', function () {
    return {
        restrict: 'E',
        controller: function ($scope) {
            console.log("collapseIconScope:");
            console.log($scope);
            $scope.test = function () {
                console.log($scope);
            }
        },
        link: function (scope, element, attrs) {
        },
        template: '\
<div class="collapse-icon" ng-click="test()">\
<span class="icon-line"></span>\
<span class="icon-line"></span>\
<span class="icon-line"></span>\
</div>'
    }
});

【问题讨论】:

    标签: javascript angularjs


    【解决方案1】:

    您看到了 2 个不同的范围,因为您进行了两次转换:一次在模板中使用 ng-transclude,另一个 - 使用名为 linker 的 transclude 函数。

    带有ng-transclude 的转入作用域通常从指令的父级(即外部作用域)继承,而您的转置函数使用指令的作用域作为转入作用域。

    根据您的要求,您需要手动创建一个从指令的隔离范围继承的子范围:

    // navBar directive's function
    pre: function (scope, element, attrs, navbarCtrl, transclude) {
       var childScope = scope.$new(false);
       // ...
    
       transclude(childScope, function(clone){
          element.append(clone);
       })
    }
    

    【讨论】:

    • 如果我错了,请纠正我,但我相信默认情况下,ng-transclude 创建的作用域是指令作用域的兄弟(指令作用域的父作用域的子代)。 This issue 仍然开放,因此已经讨论过更改此设置,但我认为它尚未进入稳定版本。
    • @JoeEnzminger,我检查了master分支的代码,虽然很简短,所以我可能弄错了。我再看看。
    • @JoeEnzminger,啊,我明白了 - 我在谈论指令是 $parent 的子父关系,而问题实际上是关于原型继承 - 在哪里,正确地,包含默认范围(与ng-transclude 一样)从指令的父级继承。修复了答案,谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多