兰 亭 墨 苑
期货 · 量化 · AI · 终身学习
首页
归档
编辑文章
标题 *
URL 别名 *
内容 *
(支持 Markdown 格式)
jsbox的webview和网页之间是如何交互的,用我们的这例子进行说明 在这个例子中,JSBox 的 WebView(原生应用容器)与网页(HTML/JS)之间的交互,本质上是 单向的“指令注入”。 可以将 JSBox 想象成一个遥控器,而网页是电视机。 以下是具体的交互流程说明: 1. 准备工作:在网页端“开门” ( ui.js ) 默认情况下,现代前端开发(使用 ES6 模块)是封闭的。就像电视机的内部电路是封装好的一样,外部无法直接触碰。 为了让 JSBox 能控制网页,我们需要在网页的全局作用域( window 对象)上暴露接口。这就像是在电视机上安装了一个红外线接收口。 代码位置: assets/js/ui.js (末尾) javascript // 我们做的事情: Object.assign(window, { showAIInterpretation, // 暴露 AI 解读函数 toggleScrollMode, // 暴露 卷轴模式函数 // ... 其他函数 }); * 原理:window 是浏览器的全局对象。只要挂载在 window 上的函数,任何在当前页面运行的脚本都可以直接调用(例如 window.showAIInterpretation())。 2. 发送指令:JSBox 端注入代码 (诗词.js) 当您在 JSBox 的导航栏点击按钮时,JSBox 会通过 eval 方法,将一段字符串形式的 JavaScript 代码“注射”到 WebView 中去执行。 代码位置: jsbox/诗词.js javascript // 1. 获取 WebView 组件 const webView = $("web"); // 2. 准备要执行的脚本字符串 // 这里的字符串就是在网页控制台里敲的代码 let script = "window.showAIInterpretation && window.showAIInterpretation();"; // 3. 注入并执行 webView.eval({ script: script + " null;" }); * $("web"):获取原生 UI 中的 WebView 视图对象。 * webView.eval(...):这是核心方法。它告诉 WebView:“请在你当前的页面上下文中,运行这段 JavaScript 代码”。 3. 特殊处理:解决返回值问题 在我们的调试过程中,您遇到了 执行JavaScript返回结果的类型不受支持 的错误。 * 原因: showAIInterpretation 是一个 async (异步) 函数,它执行后会返回一个 Promise 对象。JSBox 的 eval 尝试将这个复杂的 Promise 对象传回给原生层(JSBox),但它无法序列化这个对象,所以报错。 * 解决:我们在脚本末尾加了 null;。javascript script: "window.showAIInterpretation(); null;" 这样,整段脚本的返回值就变成了 null(一个简单类型),JSBox 就能愉快地处理了,而网页端的函数依然在后台默默执行。 总结交互图解 mermaid graph TD A[JSBox 原生层] -->|用户点击按钮| B(JSBox 脚本 handler) B -->|构建脚本字符串| C{webView.eval} C -->|注入 JS 代码| D[WebView 网页层] D -->|查找 window 对象| E[window.showAIInterpretation] E -->|执行网页逻辑| F[更新网页 DOM / 显示 AI 弹窗] 核心结论: 交互的关键在于 网页端通过 window 暴露函数,JSBox 端通过 eval 调用这些函数。这就是为什么我们之前必须修改 ui.js 才能让 JSBox 的按钮生效的原因。 script: "window.showAIInterpretation(); null;"这里不太明白,为何加null就可以 这是一个非常好的技术细节问题。 在 JavaScript 中,一段脚本的返回值,通常是这段脚本中“最后一条语句”的执行结果。 让我们看看不加 null 时发生了什么: 1. 脚本内容:window.showAIInterpretation(); 2. 执行过程:浏览器执行这个函数。 3. 函数特性: showAIInterpretation 是一个 async 函数。在 JavaScript 中,async 函数调用后,必定会立即返回一个 Promise 对象(代表“将来会完成的任务”)。 4. 脚本返回值:所以,整段脚本的返回值就是一个 Promise 对象。 5. JSBox 的困境:JSBox 的 webView.eval 机制会尝试获取脚本执行后的返回值,并将其从 Web 环境(WebView)传递回原生环境(JSBox)。 * JSBox 支持传递简单类型:数字、字符串、布尔值、null、简单的 JSON 对象。 * 不支持传递复杂对象:Promise、DOM 节点、函数 等。 * 当它试图“打包”(序列化)这个 Promise 对象传回去时,发现做不到,于是报错:“类型不受支持”。 现在看看加了 null 之后: 1. 脚本内容:window.showAIInterpretation(); null; 2. 执行过程: * 先执行第一句:window.showAIInterpretation()。函数启动了,开始在网页里跑(虽然它返回了一个 Promise,但我们没有用变量去接它,它就飘在空中了)。 * 接着执行第二句:null;。这是一个表达式,它的值就是 null。 3. 脚本返回值:整段脚本的返回值变成了最后一句的结果,也就是 null。 4. JSBox 的反应:JSBox 看到返回值是 null,这是一个它认识的简单类型,于是它很高兴地将其传回,没有任何错误发生。 打个比方: * 不加 null:您让工人(WebView)去干活(执行函数),工人干完活后,试图把整个“施工现场”(Promise 对象)搬回来给您看。您(JSBox)说:“这太大了,我搬不动,报错!” * 加了 null:您让工人去干活,然后说:“干完活你给我一张白纸(null)就行”。工人干完活,递给您一张白纸。您接过来一看,没问题,任务完成。 所以,加 null 的作用就是强制覆盖脚本的最终返回值,用一个安全的、无意义的值来替代原本那个无法传递的复杂对象。
配图 (可多选)
选择新图片文件或拖拽到此处
标签
更新文章
删除文章