【问题标题】:Angular directive implement prototypeAngular 指令实现原型
【发布时间】:2014-01-26 06:10:20
【问题描述】:

我正在尝试在画布中实现我的游戏到角度指令,但我不知道如何实现我的类“原型”

我的代码在 coffeeScript 中,但 javascript 不是问题 :)

我的指令:

angular.module("tetris", []).directive("tetris", ($timeout) ->
 restrict: "E"
 transclude: true
 scope: {}
 link: ($scope, $element, $log) ->
  game = new Game($element.children()[0],$element.children()[1],$element.children()[2])
  game.initGame()
   document.onkeydown=(e)->
    game.keyDown(e);
   document.onkeyup=(e)->
    game.keyUp(e);
  return
 template:"<div class=\"row relative\" id=\"canvas\">"+
 "<canvas class=\"absolute\" width=\"120\" height=\"250\" style=\"z-index:1\">"+
 "Your browser is not supporting canvas"+
 "</canvas>"+
 "<canvas class=\"absolute\" width=\"120\" height=\"250\" style=\"z-index:2\"></canvas>"+
 "<canvas class=\"absolute\" width=\"120\" height=\"250\" style=\"z-index:3\"></canvas>"+
 "</div>"
 replace: true
)

这是我的 eventHandler 类,我想将其实现为指令以将变量和事件提升到范围。这个类是从 Game 类中调用的。

基本上我想将变量从游戏原型提升到指令的父范围

class EventHandler
 constructor:->
  @scoreElm = document.getElementById('score')
  @levelElm = document.getElementById('level')
  @bombElm = document.getElementById('bomb')
  @nextElm = document.getElementById('next')

 updateScore:(score)->
  @scoreElm.innerHTML=score

 setBombCountDown:(time)->
  @bombElm.style.display.block
  @bombElm.innerHTML=time

 hideBombCountDown:->
  @bombElm.style.display.none

//编辑:

我想出了如何去做,但我觉得这不是正确的方法。你有什么建议可以做得更好吗?

angular.module("tetris", []).directive("tetris", ($timeout) ->
  restrict: "E"
  transclude: true
  scope: false
  link: ($scope, $element, $log) ->
    class EventHandler
      updateScore:(score)->
        $scope.score = score
        $scope.$apply()

      setBombCountDown:(time)->
        $scope.bombTime=time
        $scope.$apply()

      hideBombCountDown:->
        $scope.bombTime=null
        $scope.$apply()

    game = new Game($element.children()[0],$element.children()[1],$element.children()[2],EventHandler)
    game.initGame()
    document.onkeydown=(e)->
      game.keyDown(e);
    document.onkeyup=(e)->
      game.keyUp(e);
    return

  template:"<div class=\"row relative\" id=\"canvas\">"+
  "<canvas class=\"absolute\" width=\"120\" height=\"250\" style=\"z-index:1\">"+
  "Your browser is not supporting canvas"+
  "</canvas>"+
  "<canvas class=\"absolute\" width=\"120\" height=\"250\" style=\"z-index:2\"></canvas>"+
  "<canvas class=\"absolute\" width=\"120\" height=\"250\" style=\"z-index:3\"></canvas>"+
  "</div>"
  replace: true
)

【问题讨论】:

    标签: angularjs coffeescript angularjs-directive prototype


    【解决方案1】:

    现在,您的指令正在通过直接向其添加任意成员来操纵其父作用域,这在您的指令和外部世界之间创建了一种隐式接口。这种方法容易出错且难以维护。

    解决方案

    在构建可重用指令时,通常使用isolate scope,它通过指令元素上的属性公开其成员。这样,父作用域可以决定将哪些属性与指令的成员绑定。

    作为一个例子来说明这一点,下面是你可以如何重组你的 tetris 指令:

    .directive('tetris', function ($timeout) {
        return {
            restrict: 'E',
            scope: {
                score: '=',
                bombTime: '='
            },
            link: function (scope, el) {
                // Same code as in your example
            }
        };
    };
    

    这里的主要区别是作用域是isolate(意味着我们的指令无法“污染”父作用域)并且我们将scorebombTime属性绑定到我们指令的dom元素上的属性, 父作用域可以安全访问。

    注意 - 似乎没有理由使用transclude: true,因为您的指令不会以任何方式将父视图提供给它的内容合并到其行为中。

    使用指令现在看起来像这样:

    <tetris score="myScore" bomb-time="myBombTime"></tetris>
    <span>Score: {{myScore}}</span>
    <span>Time: {{myBombTime}}</span>
    

    现在,您的指令的用户可以选择将哪些范围成员与游戏的 scorebombTime 属性关联(在此示例中为 myScoremyBombTime 以说明它们属于父范围)。

    结论

    虽然这种编写指令的方法一开始可能看起来过于冗长,但如果您打算更改指令所在页面的结构,请将指令放入已经设置了不同范围成员的页面中,这一点很重要用于记录分数和时间,或者如果您打算为您的代码编写单元测试。

    【讨论】:

    • 谢谢。我已经这样做了,但我遇到了一个问题。我有两个由网页中的按钮触发的功能。但是这个函数也会导致俄罗斯方块类中的动作,它正在调用 eventHandler 中的函数并且正在调用 $apply。所以我收到错误$apply already in progress。有没有办法避免这种情况? pastebin.com/b5K3SC5g
    • 通常当我遇到这样的问题时,我会尝试重组我的代码,以便给定操作只有一个代码路径。话虽如此,快速而肮脏的技巧是用if (!$scope.$$digest) {...}包裹你的$scope.$apply()。(stackoverflow.com/questions/12729122/…
    猜你喜欢
    • 2014-11-09
    • 2014-04-30
    • 2013-03-04
    • 2021-06-21
    • 2018-03-31
    • 2019-09-21
    • 2020-11-16
    • 2011-06-22
    • 1970-01-01
    相关资源
    最近更新 更多