jsbox的webview和网页之间是如何交互的,用我们的这例子进行说明

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())。
  1. 发送指令: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 代码”。
  1. 特殊处理:解决返回值问题
    在我们的调试过程中,您遇到了 
    执行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 之后:
  6. 脚本内容:window.showAIInterpretation(); null;

  7. 执行过程:

    • 先执行第一句:window.showAIInterpretation()。函数启动了,开始在网页里跑(虽然它返回了一个 Promise,但我们没有用变量去接它,它就飘在空中了)。
    • 接着执行第二句:null;。这是一个表达式,它的值就是 null。
  8. 脚本返回值:整段脚本的返回值变成了最后一句的结果,也就是 null。

  9. JSBox 的反应:JSBox 看到返回值是 null,这是一个它认识的简单类型,于是它很高兴地将其传回,没有任何错误发生。
    打个比方:

  • 不加 null:您让工人(WebView)去干活(执行函数),工人干完活后,试图把整个“施工现场”(Promise 对象)搬回来给您看。您(JSBox)说:“这太大了,我搬不动,报错!”
  • 加了 null:您让工人去干活,然后说:“干完活你给我一张白纸(null)就行”。工人干完活,递给您一张白纸。您接过来一看,没问题,任务完成。
    所以,加 
    null 的作用就是强制覆盖脚本的最终返回值,用一个安全的、无意义的值来替代原本那个无法传递的复杂对象。