为什么在 AngularJS 指令中弃用了 `replace: true`

Why is `replace: true` Deprecated in AngularJS Directive

我正在使用 angularjs 开发示例播放器,利用元素指令。我希望指令模板中的事件保留在指令中。换句话说,我如何在指令中使用控制器来创建仅作用于指令模板内元素的事件。

指令:

logsApp.directive('logPlayer', function() {
    return {
        restrict: 'E',
        replace: true,
        scope: {audio: '='},
        template: '<div ng-repeat="sample in audio">' +
            '{{sample.title}}' +
            '<button type="button" class="btn btn-default" ng-click="play()">Play</button>' +
            '<button type="button" class="btn btn-danger" ng-click="stop()">Stop</button>' +
            '</div>'
    };
});

让 ng-click 事件起作用的唯一方法是将事件方法放在父控制器的 $scope:

logsApp.controller('LogListController', ['$scope', '$rootScope', 'LogsService', 'SoundManager', function($scope, $rootScope, LogsService, SoundManager) {
    ...
    $scope.play = function() {
    SoundManager.sound.createSound({
        id: SoundManager.idPrefix + this.sample.id,
        url: this.sample.filename,
        autoLoad: true,
        autoPlay: false,
        onload: function() {
            this.setPosition(0);
            this.play({
                whileplaying: function() {
                    ...
                }
            });
        }
    });
};

$scope.stop = function() {
    SoundManager.sound.stopAll();
};

我如何才能将 play()stop() 事件包含在指令控制器中?

When I create a controller to the directive, and apply $scope.play = function() {}; nothing happens.

您遇到的问题是您使用的 replace: true 已被弃用。删除它,您的指令的控制器将看到点击事件。

angular.module("myApp").directive('logPlayer', function() {
    return {
        restrict: 'E',
        //replace: true,
        scope: {audio: '='},
        controller: function($scope) {
            $scope.play = function(index) {
                console.log("play clicked "+index);
            };
        },
        template: '<div ng-repeat="sample in audio">' +
        '{{sample.title}}' +
        '<button type="button" ng-click="play($index)">Play</button>' +
        '<button type="button" ng-click="stop($index)">Stop</button>' +
        '</div>'
    };
});

DEMO on JSFiddle.

来自文档:

replace ([DEPRECATED!], will be removed in next major release - i.e. v2.0)

specify what the template should replace. Defaults to false.

  • true - the template will replace the directive's element.
  • false - the template will replace the contents of the directive's element.

-- AngularJS Comprehensive Directive API

来自 GitHub:

Caitp-- It's deprecated because there are known, very silly problems with replace: true, a number of which can't really be fixed in a reasonable fashion. If you're careful and avoid these problems, then more power to you, but for the benefit of new users, it's easier to just tell them "this will give you a headache, don't do it".

-- AngularJS Issue #7636

在这种情况下,指令的 isolate 范围与 ng-repeat 指令的 inherited 范围作斗争。因此,要么删除 replace: true,要么从模板的顶部元素中删除 ng-repeat


更新

Note: replace: true is deprecated and not recommended to use, mainly due to the issues listed here. It has been completely removed in the new Angular.

替换问题:正确

有关详细信息,请参阅 AngularJS $compile Service API Reference - Issues with replace:true