ng-if反转ng-repeat渲染顺序

jam*_*mes 8 angularjs

我刚刚遇到这个,我想知道这是一个错误还是预期的行为?这只是一个显示问题的小例子.以下代码用于以下两个示例:

<body ng-app="app" ng-controller="AppCtrl">
    <item-directive ng-repeat="item in ::items" item="item"></item-directive>
</body>
Run Code Online (Sandbox Code Playgroud)


angular
    .module('app', [])
    .controller('AppCtrl', AppCtrl)
    .directive('itemDirective', itemDirective)
    .factory('model', model);


function AppCtrl($scope, model) {

    $scope.items = model.getItems();
} 

function itemDirective() {

    return {
        restrict: 'E',
        replace: true,
        scope: {
            item: '='
        },
        templateUrl: 'item-directive.html'
    };
}

function model() {

    return {
        getItems: getItems
    }

    function getItems() {

        return [
            {
                type: 'test',
                title: 'test 1'
            },
            {
                type: 'test',
                title: 'test 2'
            },
            {
                type: 'test',
                title: 'test 3'
            }
        ];
    }
}
Run Code Online (Sandbox Code Playgroud)

第一个示例有这个item-directive.html,它按预期以正确的顺序呈现

<div>

    <span>{{::item.title}}</span>

</div>
Run Code Online (Sandbox Code Playgroud)

没有ng-if的Plunkr

但是第二个例子 - 它有以下item-directive.html - 包含一个ng-if,这导致列表以相反的顺序呈现?

<div ng-if="item.type == 'test'">

    <span>{{::item.title}}</span>

</div>
Run Code Online (Sandbox Code Playgroud)

使用ng-if的Plunkr


--------更新----------

我刚刚注意到(这与@ squiroid的答案中提到的问题有关)隔离范围在这个例子中实际上并不起作用.它似乎是,但是通过,而不是隔离范围,item可用于item-directive范围(或者更确切地说是最终ng-repeat的范围).如果您尝试在隔离范围上设置任何其他值,即使它们显示在传递给指令的链接和控制器函数的范围上(可以在plnkr的控制台输出中看到),它们也不可用于模板.除非你删除replace.

显示残破的孤立范围的Plunkr

当更换时,Plunkr显示固定的隔离范围:false


---更新2 ---

我已经更新了两个示例,以显示一旦删除隔离范围后问题仍然存在

没有ng-if和没有隔离范围的Plunkr

具有ng-if和没有隔离范围的Plunkr

还有一个新版本显示了从templateUrl到模板的更改 - 正如@Manube所建议的那样 - 显示了按预期工作的行为

具有ng-if和没有隔离范围的Plunkr使用模板而不是templateUrl

Man*_*ube 1

与templateUrl有关,是异步的;

如果将 templateUrl 替换为

 template:'<div ng-if="item.type === \'test\'"><span>{{::item.title}}</span></div>'
Run Code Online (Sandbox Code Playgroud)

它将按预期工作:请参阅 plunker with template 而不是 templateUrl


<div ng-if="item.type === 'test'">当作用域准备好并且 templateUrl 已获取时,测试将执行。

由于获取模板的方式是异步的,因此无论哪个模板先返回都会执行测试并显示该项目。

现在的问题是:为什么总是最后一个模板先返回?