【问题标题】:Nested directives/controllers in angular角度嵌套指令/控制器
【发布时间】:2014-12-02 18:14:38
【问题描述】:

刚开始了解 Angular - 由于我来自 Backbone 学派,因此无法理解一些概念。

我随机选择了一个项目开始:纸牌游戏。

假设我想定义一个hand 控制器和一个card 控制器。为简单起见,我希望将它们作为指令。

这是卡片指令:

app.directive('card', function(){

    return {
        restrict:'E',
        templateUrl:'card.html',
        controller:function($scope){
            this.suit = 'clubs';
            this.rank = 'a';
            this.suitClass = function(){
                return this.suit + '-' + this.rank;
            }
        },
        controllerAs:'card'
    };
});

这里是手动指令:

app.directive('hand', function(){

    return {
        restrict:'E',
        template:'hand.html',
        controller:function($scope){
            this.cards = [
                {suit:'clubs', rank:'a'},
                {suit:'spades', rank:'10'},
                {suit:'hearts', rank:'2'},
                {suit:'diamonds', rank:'k'}
            ];
        },
        controllerAs:'hand'
    }
});

使用following plunker,我希望能够简单地放入<hand></hand> 元素并让angular 为我完成所有工作。在我看来,<hand> 指令中应该有代表不同花色的卡片。我错过了什么?目前,正如您在 plunker 中看到的那样,嵌套的控制器/指令无法正确实例化视图。

我是否以 MVC 方式思考太多? OOP 困扰着我吗?还是 Angular 的设计很糟糕?

【问题讨论】:

  • Forked your plunker 进行了一些小的更改,来自 controllerAs 的“card”和来自 repeat 的“card”在那个范围内有点崩溃了。它远非完美的解决方案,但希望尽可能少地进行更改,以便您了解如何设置它来工作。
  • @JimL 感谢您的支持。那么我是否正确假设两个视图之间没有真正的关系,接受来自hand 的属性通过$scope 命名空间组合添加到新的card 中?

标签: javascript angularjs angularjs-directive angularjs-ng-repeat


【解决方案1】:

我不能 100% 确定我理解你的问题,但我认为这是一种更好的写法:

var app = angular.module('app', []);

app.directive('card', function(){

    return {
        restrict:'E',
        templateUrl:'card.html',
        replace: true,
        link: function ($scope, element, attrs){
            $scope.suit = 'clubs';
            $scope.rank = 'a';
            $scope.suitClass = function(){
                return this.suit + '-' + this.rank;
            }
        }
    };
});

app.directive('hand', function($compile){

    return {
        restrict:'E',
        templateUrl:'hand.html',
        link:function($scope, element, attrs){
            $scope.cards = [
                {suit:'clubs', rank:'a'},
                {suit:'spades', rank:'10'},
                {suit:'hearts', rank:'2'},
                {suit:'diamonds', rank:'k'}
            ];
        }
    }
});

html 可以是这样的: (手指令模板)

<div>
  <card ng-repeat="card in cards"></card>
</div>

(卡片指令模板)

<div ng-class="card.suitClass()">
{{ suit }}
</div>

【讨论】:

  • 感谢您的回答。但是你能解释一下link希望在这里实现什么吗?我有recreated your code in plunker,它似乎正在用div 替换card 元素,并且无法调用suitClass 方法进行适当的样式设置。
【解决方案2】:

我将通过自上而下通过将被调用的元素/对象的顺序来解释问题:

手指令:

到目前为止,该指令还可以。但是 $compile 参数和 $scope 参数没有被使用并且应该被移除。更清楚地说,我将它应用于可变手,但它不会改变应用程序的行为。

app.directive('hand', function(){

  return {
    restrict:'E',
    templateUrl:'hand.html',
    controller:function() {
      var hand = this;
      hand.cards = [
        {suit:'clubs', rank:'a'},
        {suit:'spades', rank:'10'},
        {suit:'hearts', rank:'2'},
        {suit:'diamonds', rank:'k'}
      ];
    },
    controllerAs:'hand'
  }
});

hand.html:

您从未将 ng-repeat 的当前卡片传递给卡片指令。 这样,您只生成卡片模板乘以卡片数量,但从不使用实际值。

我删除了过时的 div 标签并将 hand.html 增强为:

<card ng-repeat="card in hand.cards" card-model="card"></card>

这样我可以从卡片指令中的手牌视图中获取每张卡片。

卡片指令:

首先我删除 $scope 变量,因为它从未使用过,也不会在这里使用。

这个功能相当不完整。至少它缺少您要使用的卡值。但是这里的一个主要问题是 this 的上下文绑定到调用者。更准确地说,您在 suitClass 函数内部使用 this,但您想使用控制器的套装和等级值。 this 不指向控制器函数,而是指向新创建的 suitClass 函数,它不知道任何这些值。对于那个问题,您应该引入一个变量来保存上下文并以这种方式访问​​值。我添加了绑定到元素属性的范围变量 cardModel 以获得所需的值。我添加了 bindToController: true 来访问作为 card.cardModel 而不是纯 cardModel 的传入模型:

app.directive('card', function(){
  return {
    restrict:'E',
    scope: {
      cardModel: '='
    },
    templateUrl:'card.html',
    controller:function(){
      var card = this;
      console.log(card.cardModel)
        card.suitClass = function(){
            return card.cardModel.suit + '-' + card.cardModel.rank;
        }
    },
    controllerAs:'card',
    bindToController: true
  };
});

card.html:

这个观点没问题。我只应用了我的更改:

<div ng-class="card.suitClass()">{{ card.cardModel.rank }}</div>

我希望它仍然对任何人有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-27
    • 1970-01-01
    • 2015-01-29
    • 2014-12-23
    • 1970-01-01
    • 1970-01-01
    • 2016-06-21
    • 1970-01-01
    相关资源
    最近更新 更多