如何使用blazor绑定文档事件

时间:2019-03-26 10:33:21

标签: .net-core blazor

我尝试在Blazor上编写一个简单的蛇游戏,但找不到任何将事件绑定到文档上的方法。
有机会将事件绑定到不同的元素上,例如 div input
例如:<input onkeypress="@KeyPressInDiv"/>
public void KeyPressInDiv(UIKeyboardEventArgs ev) {....}
我想,对于javascript方法document.onkeydown = function (evt) {}应该有一个类比 我发现了解决此问题的几种方法:
1)使用JS进行绑定并调用blazor代码(摘自https://github.com/aesalazar/AsteroidsWasm

document.onkeydown = function (evt) {
  evt = evt || window.event;
  DotNet.invokeMethodAsync('Test.ClientSide', 'JsKeyDown', evt.keyCode);

  //Prevent all but F5 and F12
  if (evt.keyCode !== 116 && evt.keyCode !== 123)
      evt.preventDefault();
};

document.onkeyup = function (evt) {
  evt = evt || window.event;
  DotNet.invokeMethodAsync('Test.ClientSide', 'JsKeyUp', evt.keyCode);

  //Prevent all but F5 and F12
  if (evt.keyCode !== 116 && evt.keyCode !== 123)
      evt.preventDefault();
};

,并在c#中使用 [JSInvokable] 和事件标记的方法实现静态类。
这项工作有效,但会导致每台印刷机出现严重的延迟
2)可以在上面添加输入标签并绑定事件。
这确实比以前更快,但是:
-它主要看起来像个杂种,然后是解决方案
-我们无法捕获许多动作,例如Up / DownArrow

是否有直接方法绑定blazor的文档事件?
更新1:我创建了一个简单的项目,以更好地解释我尝试达到的目标。 https://github.com/XelMed/BlazorSnake
Snake有3种实现方式:
1)纯js-这是预期的行为
2)在blazor中使用js-使用JsInterop从JS代码调用blazor函数
3)使用输入标签-在输入标签上绑定事件以控制Snake

4 个答案:

答案 0 :(得分:0)

您可以仅使用所需的事件标签(onkeyup / onmousemove ....)将事件直接绑定到C#方法。

@page "/"

<div>
    <input type="text" onkeyup=@KeyUp />
</div>
@functions {
    void KeyUp(UIKeyboardEventArgs e)
    {
        Console.WriteLine(e.Key);
    }

    protected override Task OnInitAsync()
    {
        return Task.CompletedTask;
    }
}

答案 1 :(得分:0)

"Is there a direct way for binding on documents events from blazor?"

Nyet 

在Blazor中,您可以执行以下操作:

<input type="button" onclick="window.alert('Hello world!')" />

也许这可以给您一些想法...

希望这对您有帮助...

答案 2 :(得分:0)

也许使用JsInterop向文档中添加一个事件侦听器,并为该事件分配一个匿名函数,该函数使用偶数参数调用C#方法。

例如您的JsInterop.js:

document.addEventListener('onkeypress', function (e) {
    DotNet.invokeMethodAsync('Snake', 'OnKeyPress', serializeEvent(e))
});

将serializeEvent用作Follos以避免某些古怪:

var serializeEvent = function (e) {
    if (e) {
        var o = {
            altKey: e.altKey,
            button: e.button,
            buttons: e.buttons,
            clientX: e.clientX,
            clientY: e.clientY,
            ctrlKey: e.ctrlKey,
            metaKey: e.metaKey,
            movementX: e.movementX,
            movementY: e.movementY,
            offsetX: e.offsetX,
            offsetY: e.offsetY,
            pageX: e.pageX,
            pageY: e.pageY,
            screenX: e.screenX,
            screenY: e.screenY,
            shiftKey: e.shiftKey
        };
        return o;
    }
};

在您的C#代码中,您将拥有:

[JSInvokable]
public static async Task OnMouseDown(UIMouseEventArgs e){
    // Do some stuff here
}

答案 3 :(得分:0)

我和您有相同的要求,并且我设法使用invokeMethodAsync将文档事件(例如keydown)连接到我的Razor方法,但是后来我发现如果Blazor提供了自动DOM差异和更新功能,我就错过了Blazor提供的功能。 Razor方法更改绑定到HTML元素的某些状态(例如,控制div元素的可见性)。

(根据我对Blazor的有限了解),通常Blazor在WebAssembly方法的返回数据中返回更新DOM所需的任何状态数据。 但是,如果您使用JavaScript的invokeMethod或invokeMethodAsync,则必须自己管理返回和使用此数据,但这可能会有问题,因为您的更新可能与Blazor的DOM状态视图冲突。

因此,我想出了一种巧妙的方法,可以在Razor视图中生成隐藏的按钮,例如:

<button id="arrow-left-button" @onclick="HandleArrowLeftPress"></button>

然后在JavaScript方面,我连接了一个文档事件,该事件通过ID查找该按钮并对其调用.click():

document.getElementById('arrow-left-button').click();

我知道这看起来确实很糟糕,但是它确实适用于我所做的事情,即使用箭头键在屏幕上移动绝对定位的元素。

如果有人知道更简洁的方法(例如如何在处理程序回调中从JavaScript端通过名称强制更新Razor视图),请告诉我。