CEF3 与 HTML 的 JS 交互示例
目录
1. CEF3 项目端(注册 JS 交互事件)
用于注册 JS 可调用的 C++ 函数,并绑定事件处理类。
代码示例
volcano
变量 JS交互事件 <类型 = 类_FBrowser_事件智能指针>
JS交互事件.创建 (类_FBrowser_JS交互事件测试)
FBrowser_JS交互_注册 ("cefQuery", "cefQueryCancel", JS交互事件)
FBrowser_JS交互_注册 ("cefQuerytest", "cefQueryCanceltest", JS交互事件)关键说明
类_FBrowser_JS交互事件测试:需实现 C++ 端逻辑,处理来自 JS 的请求。- 注册的接口:
- 第一组:
cefQuery(发送请求) /cefQueryCancel(取消请求) - 第二组:
cefQuerytest/cefQueryCanceltest
- 第一组:
2. HTML 前端端(调用 CEF3 并接收返回数据)
通过 cefQuery 向 CEF3 发送请求,并在回调中处理返回数据。
HTML 完整代码
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Test Cef Query</title>
<script type="text/javascript">
var request_id;
// 第一条通道交互
function doQuery() {
request_id = window.cefQuery({
request: document.getElementById("query").value,
persistent: true,
onSuccess: function(response) {
alert(response); // C++ 返回的数据
},
onFailure: function(code, msg) {
alert("错误: " + code + " - " + msg);
}
});
}
// 第二条通道交互
function doQuery1() {
request_id = window.cefQuerytest({
request: document.getElementById("query1").value,
persistent: true,
onSuccess: function(response) {
alert(response);
},
onFailure: function(code, msg) {
alert("错误: " + code + " - " + msg);
}
});
}
// 取消请求
function doQueryCancel() {
window.cefQueryCancel(request_id);
}
</script>
</head>
<body>
<form>
Query String1:
<input type="text" id="query" value="你好CefQuery" />
<input type="button" value="SendQuery" onclick="doQuery()" />
<input type="button" value="Cancel" onclick="doQueryCancel()" />
Query String2:
<input type="text" id="query1" value="GiveMeMoney" />
<input type="button" value="SendQuery1" onclick="doQuery1()" />
</form>
</body>
</html>关键功能
window.cefQuery:向 CEF3 发送请求,支持参数:request:传递的数据(字符串或 JSON)。persistent:是否允许后续取消请求。onSuccess:成功回调,接收 C++ 返回的数据。onFailure:失败回调,返回错误码和消息。
window.cefQueryCancel:取消未完成的请求(需与persistent: true配合使用)。
3. 完整交互流程
HTML->>CEF3: window.cefQuery({ request: "data" })
CEF3->>C++: OnQuery(request, callback)
C++-->>CEF3: callback->Success("响应数据")
CEF3-->>HTML: onSuccess("响应数据")4. 注意事项
- 注册一致性:
- CEF3 的
FBrowser_JS交互_注册名称需与 HTML 中的window.cefQuery完全匹配。
- CEF3 的
- C++ 实现:
- 确保
类_FBrowser_JS交互事件测试正确处理OnQuery和OnQueryCanceled。
- 确保
- 错误排查:
- 如果
cefQuery未定义,检查 CEF3 是否成功注册接口。 - 如果无响应,检查 C++ 回调是否调用了
callback->Success。
- 如果
- 扩展建议:
- 使用 JSON 格式化请求数据(如
request: JSON.stringify({cmd: "test"}))。 - 在 C++ 端解析 JSON 并返回结构化数据。
- 使用 JSON 格式化请求数据(如
5、CEF3和VUE3交互示例
VUE代码
javascript
<template>
<button class="btn batch-open-btn" @click="batchOpen" :disabled="!hasSelectedBrowsers">
<i class="icon">▶</i> 批量打开
</button>
</template>
<script>
batchOpen() {
if (!this.hasSelectedBrowsers) return;
// 获取选中的浏览器
const selectedBrowsers = this.browsers.filter(browser => browser.selected);
const total = selectedBrowsers.length;
let completed = 0;
let failed = 0;
const that = this;
// 显示批量操作开始的通知
ElMessage({
message: `开始批量打开 ${total} 个浏览器...`,
type: 'info'
});
// 为每个浏览器执行打开操作
selectedBrowsers.forEach(browser => {
try {
const index = this.browsers.indexOf(browser);
const rowNumber = index + 1; // 获取行号(从1开始)
window.cefQuery({
request: JSON.stringify({
cmd: 'openBrowser',
browserId: browser.id || '未知ID',
browserUuid: browser.uuid,
proxyIp: browser.proxyIp || '',
rowIndex: index,
rowNumber: rowNumber // 传入行号
}),
persistent: true,
onSuccess: function(response) {
console.log('浏览器打开成功:', response);
// 解析响应,更新浏览器ID和状态
try {
const result = JSON.parse(response);
if (result && result.browserId) {
browser.id = result.browserId;
}
that.updateStatus(browser, '已打开');
} catch (e) {
console.error('解析响应失败:', e);
that.updateStatus(browser, '已打开');
}
completed++;
// 全部完成后显示结果
if (completed + failed === total) {
if (failed > 0) {
ElMessage({
message: `批量打开完成: ${completed} 个成功, ${failed} 个失败`,
type: 'warning'
});
} else {
ElMessage({
message: `成功打开所有 ${completed} 个浏览器`,
type: 'success'
});
}
}
},
onFailure: function(code, msg) {
console.error('浏览器打开失败:', code, msg);
failed++;
// 全部完成后显示结果
if (completed + failed === total) {
ElMessage({
message: `批量打开完成: ${completed} 个成功, ${failed} 个失败`,
type: 'warning'
});
}
}
});
} catch (e) {
console.error('调用cefQuery出错:', e);
failed++;
// 开发环境下不再自动赋值ID和修改状态
if (process.env.NODE_ENV === 'development') {
console.log('开发环境:CEF3环境会在此处赋值ID并更新状态为已打开');
// browser.id = 'test-' + Date.now() + '-' + Math.floor(Math.random() * 1000);
// that.updateStatus(browser, '已打开');
completed++;
failed--;
}
// 全部完成后显示结果
if (completed + failed === total) {
ElMessage({
message: `批量打开完成: ${completed} 个成功, ${failed} 个失败`,
type: 'warning'
});
}
}
});
}
</script>6、VUE3的JS方法暴露全局给CEF3调用示例
<script>
export default {
mounted() {
console.log("组件已挂载");
// 检查是否是首次加载
this.isFirstLoad = localStorage.getItem('hasBrowsersLoaded') !== 'true';
console.log("是否首次加载:", this.isFirstLoad);
this.loadBrowsersFromStorage();
// 设置已加载标志
if (this.isFirstLoad) {
localStorage.setItem('hasBrowsersLoaded', 'true');
}
// 全局更新浏览器信息的统一方法
window.updateBrowserInfo = (data) => {
if (!data || data.rowIndex === undefined) {
console.error('更新浏览器信息失败: 无效的数据格式或缺少rowIndex');
return;
}
const index = parseInt(data.rowIndex, 10);
if (index < 0 || index >= this.browsers.length) {
console.error(`更新浏览器信息失败: 索引 ${index} 超出范围`);
return;
}
const browser = this.browsers[index];
let updated = false;
// 更新浏览器ID
if (data.cmd === 'updateBrowserId' && data.browserId !== undefined) {
browser.id = data.browserId;
console.log(`已更新索引 ${index} 的浏览器ID为: ${data.browserId}`);
updated = true;
}
// 更新浏览器状态
else if (data.cmd === 'updateBrowserStatus' && data.status !== undefined) {
browser.status = data.status;
console.log(`已更新索引 ${index} 的浏览器状态为: ${data.status}`);
updated = true;
}
// 更新备注
else if (data.cmd === 'updateBrowserRemark' && data.remark !== undefined) {
browser.remark = data.remark;
console.log(`已更新索引 ${index} 的浏览器备注为: ${data.remark}`);
updated = true;
}
// 一次性更新多个属性
else if (data.cmd === 'updateBrowserAll') {
if (data.browserId !== undefined) {
browser.id = data.browserId;
}
if (data.status !== undefined) {
browser.status = data.status;
}
if (data.remark !== undefined) {
browser.remark = data.remark;
}
console.log(`已更新索引 ${index} 的浏览器多个属性`);
updated = true;
}
if (!updated) {
console.error(`未知的命令或缺少必要参数: ${data.cmd}`);
}
};
// 为了向后兼容,保留原来的方法,但内部调用新的统一方法
window.updateBrowserFromCef = (data) => {
if (data && data.cmd === 'updateBrowserId' && data.rowIndex !== undefined) {
window.updateBrowserInfo(data);
}
};
// 保持向后兼容的状态更新方法
window.updateBrowserStatus = (data) => {
if (data && data.rowIndex !== undefined && data.status !== undefined) {
window.updateBrowserInfo({
cmd: 'updateBrowserStatus',
rowIndex: data.rowIndex,
status: data.status
});
}
};
}
}
</script>