【问题标题】:Angular ng-repeat implementAngular ng-repeat 工具
【发布时间】:2015-06-09 05:43:04
【问题描述】:

我尝试实现 angular ng-repeat 指令,但我不明白为什么这段代码不能正常工作。

.directive("myRepeat", function() {
    return {
        transclude: "element",
        priority: 1000,
        compile: function(tElem, tAttrs) {
            var myLoop = tAttrs.myRepeat,
                    match = myLoop.match(/^\s*(.+)+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/),
                    indexString = match[1],
                    collectionString = match[2],
                    parent = tElem.parent();

            return function($scope, iElem, iAttrs, controller, $transclude) {


                    $scope.$watchCollection(collectionString, function(newCollection) {
                    var i, block, elements = [];

                    // check if elements have already been rendered
                    if (elements.length) {
                        // if so remove them from DOM, and destroy their scope
                        for (i = 0; i < elements.length; i++) {
                            elements[i].el.remove();
                            elements[i].scope.$destroy();
                        }
                        elements = [];
                    }

                    for (i = 0; i < newCollection.length; i++) {
                        $transclude(function(clone, scope) {
                            scope[indexString] = newCollection[i];
                            parent.append(clone);
                            block = {};
                            block.el = clone;
                            block.scope = scope;
                            elements.push(block);
                        });
                    }
                });
            }
        }
    }
})

和 HTML 片段

<ul ng-controller="MyCtrl">
  <li my-repeat="city in cities">{{city.name}}</li>
</ul>

我的问题是 LI 元素呈现正常,但它们不包含城市名称。请解释我为什么会这样。我了解 ng-transclude 在原始情况下的工作原理,当我们有带有 ng-transclude 元素的模板并且在我们的指令定义中指定 transclude: true 时,但我不明白它是如何与 transclude:"element" 一起工作的。 附言对不起我的英语不好。我是初学者:)

【问题讨论】:

  • 仅供参考,不推荐使用来自compile$transclude。见docs.angularjs.org/api/ng/service/$compile
  • 找到了别人的ng-repeat here 的克隆(它使用transclude fn 的非弃用形式)。请参阅 this plunker 将该实现(有效)与您的实现进行比较(希望您能看到差异)。
  • 在你的情况下编译函数中的链接器参数是transclude函数?在我的情况下,我从带有 transclude fn 参数的编译函数 LINK 函数返回。这没有被弃用还是我弄错了?

标签: javascript angularjs


【解决方案1】:

当我将它写入控制台时,我注意到您的 indexString 不正确。更改:match = myLoop.match(/^\s*(.+)+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/)match = myLoop.split(' ')

适合我的完整代码:

var app = angular.module('app', []);
app.controller("MyCtrl", function($scope){
  $scope.cities = [{
    name:'a'
  }, {name: 'b'},
  {name: 'c'}]
})

app.directive("myRepeat", function() {
    return {
        transclude: "element",
        priority: 1000,
        compile: function(tElem, tAttrs) {
            var myLoop = tAttrs.myRepeat,
                    match = myLoop.split(' '),
                    indexString = match[0],
                    collectionString = match[2],
                    parent = tElem.parent();
            console.log("match: " + match);
            console.log("index string: " + indexString);
            console.log("coll: " + collectionString);
            var elements = [];
            return function($scope, iElem, iAttrs, controller, $transclude) {


                    $scope.$watchCollection(collectionString, function(newCollection) {
                    var i;

                    // check if elements have already been rendered
                    if (elements.length) {
                        // if so remove them from DOM, and destroy their scope
                        for (i = 0; i < elements.length; i++) {
                            elements[i].el.remove();
                            elements[i].scope.$destroy();
                        }
                        elements = [];
                    }

                    for (i = 0; i < newCollection.length; i++) {
                        $transclude(function(clone, scope) {
                            scope[indexString] = newCollection[i];
                            parent.append(clone);
                            block = {};
                            block.el = clone;
                            block.scope = scope;
                            elements.push(block);
                        });
                    }
                });
            }
        }
    }
})

【讨论】:

    猜你喜欢
    • 2016-01-26
    • 1970-01-01
    • 2014-01-18
    • 1970-01-01
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    • 1970-01-01
    • 2013-10-23
    相关资源
    最近更新 更多