[摘錄] WebView2 與 JS 交互

https://docs.microsoft.com/zh-cn/microsoft-edge/webview2/gettingstarted/win32

步驟 5-腳本

託管應用還可以將 JavaScript 插入 Web 視圖。 你可以通過任務 Web 視圖執行任意 JavaScript 或添加初始化腳本。 已添加的初始化腳本將應用於所有未來的頂級文檔和子框架導航,直到被刪除,並在創建全局對象之後以及執行 HTML 文檔包括的任何其他腳本之前運行。

複製以下代碼片段並粘貼到其中 HelloWebView.cpp

C++
// Schedule an async task to add initialization script that freezes the Object object
webviewWindow->AddScriptToExecuteOnDocumentCreated(L"Object.freeze(Object);", nullptr);
// Schedule an async task to get the document URL
webviewWindow->ExecuteScript(L"window.document.URL;", Callback<ICoreWebView2ExecuteScriptCompletedHandler>(
    [](HRESULT errorCode, LPCWSTR resultObjectAsJson) -> HRESULT {
        LPCWSTR URL = resultObjectAsJson;
        //doSomethingWithURL(URL);
        return S_OK;
    }).Get());

現在,Web 視圖應該始終凍結 Object 對象並返回頁面文檔一次。

備註

腳本注入 Api \ (以及某些其他 WebView2 Api \)是異步的,如果必須按特定順序運行代碼,則應使用回調。

步驟 6-主機和 web 內容之間的通信

宿主和 web 內容也可能通過該方法互相通信 postMessage 。 在 web 視圖內運行的 web 內容可能會通過該方法向主機發布 window.chrome.webview.postMessage ,並且消息由主機上任何註冊的 ICoreWebView2WebMessageReceivedEventHandler 事件處理程序處理。 同樣,主機可以通過 " ICoreWebView2::PostWebMessageAsString 或" ICoreWebView2::PostWebMessageAsJSON 方法處理 web 內容,這由從偵聽器添加的處理程序捕獲 window.chrome.webview.addEventListener 。 通信機制允許 web 內容通過將消息傳遞給請求主機調用本機 Api 來利用本機功能。

作爲了解機制的示例,當你嘗試在 Web 視圖中打印文檔 URL 時,將發生以下步驟。

  1. 主機註冊處理程序以返回收到的消息,返回到 web 內容
  2. 主機將向註冊處理程序的 web 內容插入腳本,以便從主機打印消息
  3. 主機爲將 URL 發佈到主機的 web 內容插入腳本
  4. 將觸發主機的處理程序,並將消息 \ (URL \)返回到 web 內容
  5. 將觸發 web 內容的處理程序,並通過主機 \ (URL \)打印消息

複製以下代碼片段並粘貼到其中 HelloWebView.cpp

C++
// Set an event handler for the host to return received message back to the web content
webviewWindow->add_WebMessageReceived(Callback<ICoreWebView2WebMessageReceivedEventHandler>(
    [](ICoreWebView2* webview, ICoreWebView2WebMessageReceivedEventArgs * args) -> HRESULT {
        PWSTR message;
        args->TryGetWebMessageAsString(&message);
        // processMessage(&message);
        webview->PostWebMessageAsString(message);
        CoTaskMemFree(message);
        return S_OK;
    }).Get(), &token);

// Schedule an async task to add initialization script that
// 1) Add an listener to print message from the host
// 2) Post document URL to the host
webviewWindow->AddScriptToExecuteOnDocumentCreated(
    L"window.chrome.webview.addEventListener(\'message\', event => alert(event.data));" \
    L"window.chrome.webview.postMessage(window.document.URL);",
nullptr);

https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2/gettingstarted

Step 5 - Scripting

The hosting app can also inject JavaScript into WebView. You can task WebView to execute arbitrary JavaScript or add initialization scripts. Added initialization scripts apply to all future top level document and child frame navigation until removed, and run after the global object has been created and before any other script included by the HTML document is executed.

Copy the following code below // Step 5 - Scripting.

C++
// Schedule an async task to add initialization script that freezes the Object object
webviewWindow->AddScriptToExecuteOnDocumentCreated(L"Object.freeze(Object);", nullptr);
// Schedule an async task to get the document URL
webviewWindow->ExecuteScript(L"window.document.URL;", Callback<ICoreWebView2ExecuteScriptCompletedHandler>(
    [](HRESULT errorCode, LPCWSTR resultObjectAsJson) -> HRESULT {
        LPCWSTR URL = resultObjectAsJson;
        //doSomethingWithURL(URL);
        return S_OK;
    }).Get());

Now WebView will always freeze the Object object and return the page document once.

Note that these script injection APIs (and some other WebView2 APIs) are asynchronous, you should use callbacks if code is to be executed in a particular order.

Step 6 - Communication between host and web content

The host and the web content can also communicate with each other through postMessage. The web content running within a WebView can post to the host through window.chrome.webview.postMessage, and the message would be handled by any registered ICoreWebView2WebMessageReceivedEventHandler on the host. Likewise, the host can message the web content through ICoreWebView2::PostWebMessageAsString or ICoreWebView2::PostWebMessageAsJSON, which would be caught by handlers added from window.chrome.webview.addEventListener. The communication mechanism allows the web content to utilize native capabilities by passing messages to ask the host to call native APIs.

As an example to understand the mechanism, let's try printing out the document URL in WebView with a little detour,

  1. the host registers a handler to return received message back to the web content
  2. the host injects a script to the web content that registers a handler to print message from the host
  3. the host injects a script to the web content that posts the URL to the host
  4. the host's handler is triggered and returns the message (the URL) to the web content
  5. the web content's handler is triggered and prints the host's message (the URL)

Copy the following code below // Step 6 - Communication between host and web content,

C++
// Set an event handler for the host to return received message back to the web content
webviewWindow->add_WebMessageReceived(Callback<ICoreWebView2WebMessageReceivedEventHandler>(
    [](ICoreWebView2* webview, ICoreWebView2WebMessageReceivedEventArgs * args) -> HRESULT {
        PWSTR message;
        args->TryGetWebMessageAsString(&message);
        // processMessage(&message);
        webview->PostWebMessageAsString(message);
        CoTaskMemFree(message);
        return S_OK;
    }).Get(), &token);

// Schedule an async task to add initialization script that
// 1) Add an listener to print message from the host
// 2) Post document URL to the host
webviewWindow->AddScriptToExecuteOnDocumentCreated(
    L"window.chrome.webview.addEventListener(\'message\', event => alert(event.data));" \
    L"window.chrome.webview.postMessage(window.document.URL);",
nullptr);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章