JS 與 C++ 雙向通信實戰:基于 WebHostViewListener 的消息處理機制

前言

在現代瀏覽器和桌面應用開發中,WebView 嵌入已經成為一種非常常見的 UI 技術方案。無論是基于 Chromium 的 CEF(Chromium Embedded Framework)、Qt WebEngine,還是自研瀏覽器內核,嵌入 WebView 都能帶來極高的靈活性與跨平臺 UI 開發能力。

不過,當 HTML/JavaScript 需要與 C++ 后端交互時,如何實現 高效、安全、可維護 的雙向通信機制,就成了一個必須認真設計的問題。本文將結合 WebHostViewListener 機制,從源碼角度深入剖析 HTML/JS 與 C++ 的消息傳遞、事件處理、數據序列化等關鍵流程,并對比常見的 JSBridge、JavaScriptCore 等方案,總結優缺點與優化建議。


一、為什么需要 WebView 與 C++ 雙向通信

嵌入 WebView 的目的不僅僅是“顯示網頁”,而是利用 HTML/CSS/JS 的靈活 UI 構建能力,與 C++ 的高性能、底層資源訪問能力結合。

典型的交互場景包括:

  1. HTML/JS 調用 C++ 功能

    • 獲取本地文件列表

    • 調用系統 API(如打開文件、讀取剪貼板)

    • 訪問數據庫或加解密模塊

    • 發送網絡請求并處理復雜協議

  2. C++ 回調 HTML/JS

    • 通知前端狀態變化(如下載進度、后臺任務完成)

    • 推送實時數據(如 WebSocket 消息)

    • 動態修改前端 UI(更新 DOM 或觸發 JS 方法)

如果沒有合理的通信機制,前后端之間會出現:

  • 數據結構不統一

  • 消息無法安全傳輸

  • 調用關系混亂、難以調試

WebHostViewListener 正是為了解決這些痛點而設計的一個消息分發與事件監聽器。


二、WebHostViewListener 的定位與職責

在一個基于瀏覽器內核的應用中,WebHostViewListener 通常作為 橋接層(Bridge Layer) 的核心部分,負責監聽 WebView(瀏覽器渲染進程)與 C++ 宿主(瀏覽器主進程或宿主應用)之間的消息,并進行分發與處理。

其核心職責包括:

  1. 監聽 HTML/JS 發出的消息

    • 通過 WebView 內置的消息通道(如 window.externalchrome.sendwindow.postMessage)接收 JSON 數據

    • 解析消息并根據指令類型路由到對應的 C++ 處理邏輯

  2. 將處理結果返回給前端

    • 將 C++ 的執行結果序列化為 JSON

    • 通過 WebView 的 JavaScript 執行接口(如 ExecuteJavaScriptRunJSFunction)回調給 HTML 頁面

  3. 保持通信協議一致性

    • 定義統一的消息格式:消息類型、參數、回調 ID

    • 確保版本升級時協議向后兼容


三、消息格式設計

要實現穩定的雙向通信,首先需要一個 統一的消息格式。在 WebHostViewListener 中,常見的設計是基于 JSON 的結構化消息,例如:

{ "cmd": "getUserInfo", "params": { "userId": 12345 }, "callbackId": "cb_001" } 

字段解釋:

  • cmd:指令名,告訴 C++ 需要執行什么操作

  • params:參數對象,包含該操作需要的輸入數據

  • callbackId:回調 ID,前端用它來區分不同請求的返回

返回給前端的消息同樣保持結構化,例如:

{ "callbackId": "cb_001", "status": 0, "data": { "name": "Alice", "age": 25 } } 

這樣設計的好處是:

  • 協議簡單明了

  • 支持異步回調

  • 易于調試與擴展


四、WebHostViewListener 的工作流程

假設我們有這樣一個交互場景:

  1. 前端 HTML 通過 JavaScript 發送一個 getUserInfo 請求

  2. C++ 收到消息后查詢數據庫

  3. 查詢結果再通過 WebView 回調給前端

對應的流程圖如下:

HTML/JS ----(消息)----> WebHostViewListener(C++) <---(回調)----- 

1. 前端發送消息

前端調用封裝的發送方法,例如:

function sendMessage(cmd, params, callback) { const callbackId = "cb_" + Date.now(); window.WebHostView.postMessage(JSON.stringify({ cmd: cmd, params: params, callbackId: callbackId })); callbacks[callbackId] = callback; } sendMessage("getUserInfo", { userId: 12345 }, function(response) { console.log("User Info:", response.data); }); 

2. WebHostViewListener 接收消息

在 C++ 中,WebHostViewListener 會注冊一個 消息回調函數

void WebHostViewListener::OnMessageReceived(const std::string& json_message) { auto msg = ParseJson(json_message); std::string cmd = msg["cmd"]; if (cmd == "getUserInfo") { HandleGetUserInfo(msg["params"], msg["callbackId"]); } } 

3. C++ 處理邏輯

void WebHostViewListener::HandleGetUserInfo(const Json::Value& params, const std::string& callbackId) { UserInfo info = database_.GetUser(params["userId"].asInt()); Json::Value result; result["name"] = info.name; result["age"] = info.age; SendCallback(callbackId, 0, result); } 

4. 回調前端

void WebHostViewListener::SendCallback(const std::string& callbackId, int status, const Json::Value& data) { Json::Value msg; msg["callbackId"] = callbackId; msg["status"] = status; msg["data"] = data; std::string json_str = msg.toStyledString(); webview_->ExecuteJavaScript("window.onNativeMessage(" + json_str + ");"); } 

五、與常見 JSBridge 的區別

你提到的 CSDN 文章中介紹的方式,更多是基于 JavaScript 調用綁定函數 的模式,例如:

  • 在 WebView 中注入一個 window.external.callCppMethod() 的接口

  • 或使用 CEF 提供的 ExecuteFunction 注冊回調

這種方式的特點:

  • 實現簡單,適合調用頻率低的功能

  • 消息結構不一定規范,容易出現維護問題

  • 缺少統一的異步回調機制

而 WebHostViewListener 的優勢在于:

  • 協議化:統一 JSON 消息格式

  • 可擴展:只需新增 cmd 處理函數即可

  • 異步友好:支持多并發調用,回調不會亂序


六、性能與安全性考慮

在大規模應用中,通信機制需要關注以下幾個點:

  1. 消息序列化與反序列化開銷

    • 頻繁 JSON 解析會有性能損耗

    • 可考慮二進制格式(如 Protobuf)優化

  2. 安全性

    • 嚴格校驗 cmd 是否在允許列表

    • 檢查 params 數據類型,防止注入攻擊

  3. 線程模型

    • UI 線程接收消息,耗時操作放到后臺線程

    • 回調 UI 必須切回主線程


七、實際案例:瀏覽器插件配置面板

以我在瀏覽器項目中的一個場景為例:

  • 前端是 HTML/JS 的插件配置界面

  • 需要讀取/寫入本地配置文件

  • 修改配置后立即生效

采用 WebHostViewListener:

  • 前端發送 "saveConfig" 消息

  • C++ 寫入 JSON 配置文件

  • 成功后回調 "status": 0

  • 前端立即刷新界面

這種模式非常清晰,擴展新功能時,只需要新增一個 cmd 分支,不會影響已有功能。


八、總結

WebHostViewListener 提供了一種結構化、可維護、擴展性強的 WebView 與 C++ 雙向通信機制,它相較于簡單的 JS 調用綁定函數模式,在復雜項目中更具優勢。

它的核心思想:

  • 協議化(統一 JSON 格式)

  • 模塊化(cmd 分發)

  • 異步化(callbackId 回調)

在瀏覽器、桌面客戶端、混合應用等場景下,都可以直接借鑒這種設計思路。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/918691.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/918691.shtml
英文地址,請注明出處:http://en.pswp.cn/news/918691.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

模板打印技術——Office XLS 打印模板:為政務土地確權定制的紙張替換利器—仙盟創夢IDE

代碼public static int cyberwin_replaceExcelandoutputPrint(string fisrcpathleurl, DataTable dtInfo, string despath){if (File.Exists(despath) true){//刪除目標文件File.Delete(despath);}File.Copy(fisrcpathleurl, despath);string 目標文件 despath;MSEXCEL.Appli…

可直接運行的 Playwright C# 自動化模板

目錄 目錄結構 1. appsettings.json&#xff08;賬號、URL、路徑配置&#xff09; 2. Program.cs&#xff08;啟動入口&#xff09; 3. SchedulerConfig.cs&#xff08;定時調度&#xff09; 4. SocialSecurityTask.cs&#xff08;自動報社保任務&#xff09; 5. QuerySo…

云平臺監控-云原生環境Prometheus企業級監控實戰

目錄 一、基于 Kubernetes 的 Prometheus 監控方案概述 1. 核心組件及功能 2. 監控流程詳解 3. 關鍵監控指標說明 二、Prometheus 與相關組件部署 1. 克隆項目代碼 2. 安裝 Prometheus Operator 3. 安裝 Prometheus Stack 4. 查看容器運行狀態 三、ServiceMonitor 配…

GPT-5 有點不太順

GPT-5 有點不太順 OpenAI 的新模型 GPT-5 盼了很久,結果一上線就問題不少。 發布會剛過,CEO 山姆?奧特曼就說,要給部分用戶恢復 GPT-4o 這些老模型的使用權限,還承認 GPT-5 上線 “比預想的坎坷”。 簡單題都做錯了 不少用戶發現,GPT-5 連一些簡單問題都答不對,比之前…

《卷積神經網絡(CNN):解鎖視覺與多模態任務的深度學習核心》

1.概述卷積神經網絡&#xff08;CNN&#xff09;是深度學習在計算機視覺領域的重要突破&#xff0c;專為處理網格狀數據&#xff08;如圖像&#xff09;設計&#xff0c;后也擴展到自然語言處理等領域。它解決了全連接網絡處理大圖像時計算代價高、特征保留差的問題&#xff0c…

React Native + Expo搭建APP項目+安卓模擬器

Expo 嘗試一下就好&#xff0c;畢竟參考代碼太少&#xff0c;相當于閉關造輪子&#xff0c;不建議。 一、需要的工具 1. node.js&#xff0c;推薦使用&#xff08;TLS版本&#xff09;&#xff0c;版本不是太低就行&#xff0c;測試用的v20.12.2的Node 2. 開發工具 VS CODE或…

第六十五章:AI的“精良食材”:圖像標注、視頻幀抽幀與字幕提取技巧

ai 數據處理前言&#xff1a;從“原始食材”到“AI盛宴”第一章&#xff1a;圖像標注&#xff1a;為AI“指點江山”1.1 什么是圖像標注&#xff1f;—— AI的“視覺標簽”1.2 分類任務&#xff1a;圖像的“身份識別”1.3 目標檢測&#xff1a;圖像的“區域識別”與“邊界框”1.…

2025 開源語音合成模型全景解析:從工業級性能到創新架構的技術圖譜

一、引言&#xff1a;開源浪潮下的語音合成技術躍遷 語音合成&#xff08;TTS&#xff09;作為人工智能領域的核心技術&#xff0c;近年來在開源社區的推動下取得了突破性進展。從早期的基于規則的拼接合成&#xff0c;到深度學習驅動的端到端模型&#xff0c;再到當前與大語言…

前端懶加載技術全面解析

懶加載(Lazy Loading)是一種優化前端性能的重要技術,核心思想是延遲加載非關鍵資源,只在需要時加載它們。 一、懶加載的基本原理 懶加載的核心思想是通過以下方式優化性能: 減少初始加載實踐: 只加載首屏所需資源 節省帶寬和內存: 避免加載用戶可能不會查看的內容 提高…

B3DM,OSGB,PLY,OBJ,S3MB,I3S這幾種格式有什么區別

B3DM、OSGB、PLY、OBJ、S3MB、I3S 都是三維模型/地理空間數據的文件格式&#xff0c;但它們的用途、結構和適用場景差別很大。1. B3DM&#xff08;Batched 3D Model&#xff09;來源/用途&#xff1a;屬于 Cesium 3D Tiles 規范&#xff0c;用于在 Cesium、Mapbox 這種 WebGIS …

Matlab(4)

一、Basic plotting1.plot&#xff08;&#xff09;plot(x,y) &#xff1a;x圖片中點的橫坐標&#xff0c;y圖片中點的縱坐標plot(y) &#xff1a;y圖片中點的縱坐標&#xff0c;x圖片中點的橫坐標默認為1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5........plot(co…

Pycharm選好的env有包,但是IDE環境顯示無包

一、異常現象 Pycharm選好的env&#xff08;yolov7&#xff09;&#xff1a; 有Numpy這個包&#xff1a; IDE環境愣是報沒有&#xff1a; 二、嘗試解決 2.1 重新啟動pycharm 重新打開.py文件&#xff1a; 還是不行&#xff1a; 看看好使的windows上的pycharm參數&#xff1a…

深入理解 Linux 下的 GDB 調試工具

引言 在軟件開發中&#xff0c;調試是一個不可避免且至關重要的環節。無論是簡單的邏輯錯誤&#xff0c;還是復雜的內存泄漏問題&#xff0c;調試工具都能幫助我們快速定位并修復問題。而在 Linux 系統中&#xff0c;GDB&#xff08;GNU 調試器&#xff09;是最強大、最常用的…

讓齒輪與斑馬線共舞:汽車文化驛站及安全教育基地的展陳實踐

當汽車文化驛站及安全教育基地的展陳項目圖紙在繪圖儀上初現輪廓時&#xff0c;我們就明確了一個核心命題&#xff1a;如何讓 “速度與激情” 的汽車文化&#xff0c;與 “規則與敬畏” 的安全教育在同一空間里和諧共生&#xff0c;而非簡單拼接。這不是兩個獨立展區的物理疊加…

Flask + Vue.js 物聯網數字大屏實現方案

我將為您創建一個精美的物聯網數字大屏,使用Flask作為后端提供數據,Vue.js作為前端展示,全部集成在單個HTML文件中實現。 設計思路 整體布局: 深色主題背景提高數據可視性 頂部標題欄顯示系統名稱和時間 中央區域分為多個數據卡片 底部顯示系統狀態信息 核心功能: 實…

Excel怎么篩選重復項?【圖文詳解】查找/刪除重復項?查找重復項公式?如何去重?

一、問題背景 在使用 Excel 整理數據時&#xff0c;我們經常會遇到重復內容。這些重復項不僅會讓表格顯得雜亂&#xff0c;還可能影響數據統計的準確性。比如學生成績表中重復的分數、員工信息表中重復的姓名等&#xff0c;都需要及時篩選出來處理。其實&#xff0c;篩選重復項…

模板打印技術——自動識別office類型 打印模板:為政務土地確權定制的替換利器—仙盟創夢IDE

代碼for (int i 0; i < tmpcount; i){string tmptable dt.Rows[i]["tmpname"].ToString().Trim();string doctype dt.Rows[i]["doctype"].ToString().Trim();if (doctype "doc"){doc_pagecount cyberwin_replacr_tmpes_files(dgvr, tmpt…

MongoDB分析insert源代碼

mongo插入單條文檔insert()> db.user.insert({ ... "name": "alice", ... "age": 28 ... }); WriteResult({ "nInserted" : 1 }) >MongoDB插入文檔代碼調用鏈如下&#xff1a;mongo/db/commands/write_commands/write_c…

react路由跳轉與路由懶加載等(對照vue來說一說不同之處)

前言&#xff1a;react路由跳轉與路由懶加載等路由懶加載&#xff1a;使用 loadable/component 插件來實現安裝&#xff1a;npm i loadable/component具體使用&#xff1a;1、引入loadable/component2、正常封裝的地方const HomeLoadable(()>import(./views/Home.jsx));也可…

Nginx 架構和安裝

二、.Nginx 架構和安裝 2.1 Nginx 概述 2.1.1 Nginx 介紹 Nginx&#xff1a;engine X &#xff0c;2002年開發&#xff0c;分為社區版和商業版(nginx plus ) 2019年3月11日 F5 Networks 6.7億美元的價格收購 Nginx是免費的、開源的、高性能的HTTP和反向代理服務器、郵件代理服務…