Angularjs 角度定向器原型

Angularjs 角度定向器原型,angularjs,coffeescript,angularjs-directive,prototype,Angularjs,Coffeescript,Angularjs Directive,Prototype,我试图在canvas to angular指令中实现我的游戏,但我不知道如何实现我的类“prototype” 我的代码是用coffeeScript编写的,但javascript不是问题:) 我的指示: angular.module("tetris", []).directive("tetris", ($timeout) -> restrict: "E" transclude: true scope: {} link: ($scope, $element, $log) ->

我试图在canvas to angular指令中实现我的游戏,但我不知道如何实现我的类“prototype”

我的代码是用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
)
.directive('tetris', function ($timeout) {
    return {
        restrict: 'E',
        scope: {
            score: '=',
            bombTime: '='
        },
        link: function (scope, el) {
            // Same code as in your example
        }
    };
};
//编辑:

我知道怎么做了,但我觉得这不是一个正确的方法。你对如何做得更好有什么建议吗

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
)
angular.module(“俄罗斯方块”,[]).directive(“俄罗斯方块”,($timeout)->
限制:“E”
转移:对
范围:假
链接:($scope$element$log)->
类事件处理程序
更新核心:(分数)->
$scope.score=分数
$scope.$apply()
setBombCountDown:(时间)->
$scope.bombTime=时间
$scope.$apply()
营养不良倒计时:->
$scope.bombTime=null
$scope.$apply()
游戏=新游戏($element.children()[0],$element.children()[1],$element.children()[2],EventHandler)
game.initGame()
document.onkeydown=(e)->
游戏。按键(e);
document.onkeyup=(e)->
游戏。键控(e);
返回
模板:“”+
""+
“您的浏览器不支持画布”+
""+
""+
""+
""
替换:正确
)

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

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

作为一个例子来说明这一点,下面是如何重构
俄罗斯方块
指令:

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
)
.directive('tetris', function ($timeout) {
    return {
        restrict: 'E',
        scope: {
            score: '=',
            bombTime: '='
        },
        link: function (scope, el) {
            // Same code as in your example
        }
    };
};
这里的主要区别是作用域是
隔离
(这意味着我们的指令无法“污染”父作用域),并且我们将
得分
轰炸时间
属性绑定到我们指令的dom元素上的属性,父作用域可以安全访问这些属性

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

现在使用该指令如下所示:

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

分数:{{myScore}
时间:{{myBombTime}}
现在,指令的用户可以选择与游戏的
score
bombTime
属性关联的作用域成员(
mycore
myBombTime
,在本例中说明它们属于父作用域)

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

谢谢。我是这样做的,但我遇到了一个问题。我有两个功能是由网页中的按钮触发的。但该函数也会导致俄罗斯方块类中的操作,该类在eventHandler中调用函数,并调用$apply。因此,我得到的错误
$apply已在进行中
。有没有办法避免这种情况?通常,当我遇到这样的问题时,我会尝试重新构造代码,以便给定操作只有一条代码路径。话虽如此,快速而肮脏的技巧是用
if(!$scope.$$digest){…}
()