我正在尝试在canvas中使用angular指令实现我的游戏,但我无法弄清楚如何实现我的类“原型”
我的代码是在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类调用的。
基本上我想将变量从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
)
答案 0 :(得分: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
(意味着我们的指令无法“污染”父范围)并且我们将score
和bombTime
属性绑定到我们的指令的dom元素上的属性,父作用域可以安全访问。
注意 - 似乎没有理由使用transclude: true
,因为您的指令没有将父视图提供给它的内容合并到任何行为中方式。
现在使用该指令如下所示:
<tetris score="myScore" bomb-time="myBombTime"></tetris>
<span>Score: {{myScore}}</span>
<span>Time: {{myBombTime}}</span>
现在,您的指令的用户可以选择与此游戏中的score
和bombTime
属性(myScore
和myBombTime
相关联的范围成员,以说明他们属于父范围)。
虽然这种编写指令的方法起初可能看起来过于冗长,但是如果您计划更改指令所在页面的结构,将指令放入已经设置了不同范围成员的页面,这一点很重要。保持分数和时间,或者你打算为你的代码编写单元测试。