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

4

我正在使用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()事件的包含?


1
将控制器添加到您的指令中。有关更多信息,请参见AngularJS Comprehensive Directive API - georgeawg
当我为指令创建控制器,并应用$scope.play = function() {};时,没有任何反应。http://paste.ofcode.org/MBuDatxyYf2tDXp8BhgLcq - cj5
1个回答

2
当我为指令创建控制器并应用$scope.play = function() {};时,没有任何反应。
你遇到的问题是使用了被弃用的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>'
    };
});

这是在JSFiddle上的DEMO

从文档中可以看出:

replace([已弃用!],将在下一个主要版本发布时删除 - 即v2.0)

指定模板应替换什么。默认为false

  • true - 模板将替换指令的元素。
  • false - 模板将替换指令元素的内容。

-- AngularJS Comprehensive Directive API

从GitHub上可以看到:

Caitp-- 它被弃用是因为replace: true存在已知的非常愚蠢的问题,其中一些问题无法以合理的方式修复。如果你小心并避免这些问题,那么你就更有能力了,但是为了新用户的利益,最好告诉他们“这会让你头疼,不要这样做”。

-- AngularJS Issue #7636

在这种情况下,指令的隔离作用域ng-repeat指令的继承作用域发生了冲突。因此,要么删除replace: true,要么从模板的顶部元素中删除ng-repeat


更新

注意:replace: true已被弃用,不建议使用,主要是由于以下问题。它已经在新版Angular中完全删除了。

replace: true存在的问题

有关更多信息,请参见AngularJS $compile Service API Reference - Issues with replace:true


谢谢!有效了。这是因为替换后更新了DOM,事件变得未绑定了吗? - cj5
1
ng-repeat 正在覆盖指令的作用域。通常情况下,隔离中的 ng-click 不应该能够通过继承连接到父函数。ng-repeat 破坏了 隔离 作用域。 - georgeawg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接