哪个 WebView2 事件/函数可以用来替换 ScriptNotify Webview 事件?

sch*_*ebe 3 vb.net winforms webview2

今天,我决定将一个 VB.net 应用程序中的WebView控件迁移到另一个控件WebView2

我已经安装WebView2NuGet更改了声明和初始化行(我的 VB 程序中只有 4 行,因为我使用 2 个 WebView2)。

当我构建我的应用程序时,Visual Studio 2019表明该ScriptNotify事件不是WebView2!

Private Sub wvSelect_ScriptNotify(
    sender As Object, 
    e As WebViewControlScriptNotifyEventArgs) Handles wvSelect.ScriptNotify
Run Code Online (Sandbox Code Playgroud)

使用旧WebView控件,该事件是使用windows.external.notifyJavascript 函数生成的。

function clickPlus(e) { window.external.notify("+PLUS:"); }
Run Code Online (Sandbox Code Playgroud)

哪个事件正在取代控制ScriptNotify中的事件WebView2

我有兴趣了解新事件以及如何从 Javascript 调用该事件。

Jim*_*imi 5

使用WebView2处理事件通知的一些可能场景:
另请参阅:在 WebView 中使用 JavaScript 进行扩展场景

通用初始化:

  • WebView2 实例名为myWebView2
  • 使用基本方法:例如使用JavaScriptSerializer进行JSON反序列化。您可能有 Json.Net 或 System.Text.Json。
  • 同样假设 WinForms,您还没有指定 GUI 框架

Private Async Sub Load(sender As Object, e as EventArgs) Handles MyBase.Load
    await myWebView2.EnsureCoreWebView2Async(Nothing)
End Sub
Run Code Online (Sandbox Code Playgroud)

另外,我正在使用这个简单的类模型,用于反序列化收到的 JSON 消息,因为WebView2.WebMessageReceived假定为 JSON 格式;不过,您可以传递任何您想要的字符串。

Private Class JsonEventMessage
    Public Property Element As String
    Public Property Value As String
End Class
Run Code Online (Sandbox Code Playgroud)

1 -在这种情况下,javascript 函数已在 HTML 中定义

  • 用于JSON.stringify()强调返回值是一个JSON对象
Private Async Sub Load(sender As Object, e as EventArgs) Handles MyBase.Load
    await myWebView2.EnsureCoreWebView2Async(Nothing)
End Sub
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您只需要订阅事件WebMessageReceived并反序列化 JSON:

AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceived

' [...]

Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)
    Dim message = New JavaScriptSerializer().Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())
    Console.WriteLine(message.Element)
    Console.WriteLine(message.Value)
End Sub
Run Code Online (Sandbox Code Playgroud)

注意:我使用的是e.TryGetWebMessageAsString()而不是e.WebMessageAsJson,因为后者用引号引起来(双字符串化)。当您传递简单的字符串时最好使用它。


2 -此处定义了一个可以通知消息的 JavaScript 函数HEAD,但没有在其他任何地方添加事件处理程序。
假设您将在运行时添加 HTML 元素,或者您不想在 HTML 或其他任何内容中添加事件处理程序。

Private Class JsonEventMessage
    Public Property Element As String
    Public Property Value As String
End Class
Run Code Online (Sandbox Code Playgroud)

像以前一样订阅事件WebMessageReceivedNavigationCompleted事件。加载文档时会引发此事件。我们需要此事件,因为在示例中,事件处理程序被添加到主体中的元素中,而在此之前这是不可用的。

在 中NavigationCompleted,我们可以将 JavaScript Function 添加到字符串中并调用WebView2.ExecuteScriptAsync()方法,该方法在 DOM 准备好后执行脚本,否则GetElementById()将找不到目标。

AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceived
AddHandler myWebView2.NavigationCompleted, AddressOf myWebView2_NavigationCompleted

' [...]

Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)
    Dim message = New JavaScriptSerializer().Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())
    ' [...]
End Sub

Private Async Sub myWebView2_NavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs)
    Dim func As String =
        "document.getElementById('div1').
            addEventListener('click', function(e) { 
                SomeFunction(e, '+PLUS:')
            });"
    Await myWebView2.ExecuteScriptAsync(func)
End Sub
Run Code Online (Sandbox Code Playgroud)

3 -这次,HTML 中的任何位置都没有定义 JavaScript 函数。

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript">
        function SomeFunction(e, v) {
           var json = JSON.stringify({ Element:e.target.id, Value:v });
           window.chrome.webview.postMessage(json);
        }
    </script>
</head>
<body>
    <script>
        document.getElementById("div1").addEventListener("click", function(e) {SomeFunction(e, '+PLUS:')});
    </script>
    <div id="div1">Some Text to Click</div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

案例1:
像以前一样 订阅WebMessageReceivedNavigationCompleted事件。

在 中NavigationCompleted,发布消息的 JavaScript 函数被直接添加到事件处理程序中。调用ExecuteScriptAsync()以执行脚本并将事件侦听器添加到 HTML 元素。

AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceived
AddHandler myWebView2.NavigationCompleted, AddressOf myWebView2_NavigationCompleted

' [...]

Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)
    Dim message = New JavaScriptSerializer().Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())
    ' [...]
End Sub

Private Async Sub myWebView2_NavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs)
    Dim func As String =
    "document.getElementById('div1').
        addEventListener('click', function(e) { 
            var json = JSON.stringify({Element:e.target.id, Value:'+PLUS:'});
            window.chrome.webview.postMessage(json); 
    });"
    Await myWebView2.ExecuteScriptAsync(func)
End Sub
Run Code Online (Sandbox Code Playgroud)

情况2
订阅WebMessageReceivedWebView2.CoreWebView2InitializationCompleted 在本例中,我们向文档添加一个事件侦听器,然后使用该成员以及可用于处理通知的任何其他属性或值来
确定单击了哪个元素。Event.Target

在这里,我只是将[Event].target.id[Event].target.innerText作为 JSON 属性传递。当然,您可以获取用例中所需的任何其他属性。

AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceived
AddHandler myWebView2.CoreWebView2InitializationCompleted, AddressOf myWebView2_CoreWebView2InitializationCompleted
' [...]

Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)
    Dim message = New JavaScriptSerializer().
        Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())
    ' [...]
End Sub

Private Async Sub myWebView2_CoreWebView2InitializationCompleted(
    sender As Object, 
    e As CoreWebView2InitializationCompletedEventArgs)

    Dim func as String = 
    "document.addEventListener
        ('click', function(e) {
            window.chrome.webview.postMessage(
                JSON.stringify({ Element:e.target.id, Value:e.target.innerText })
            );
       });"
    Await myWebView2.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(func)
End Sub
Run Code Online (Sandbox Code Playgroud)