惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

U
Unit 42
T
The Blog of Author Tim Ferriss
H
Help Net Security
博客园 - 叶小钗
云风的 BLOG
云风的 BLOG
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
D
DataBreaches.Net
博客园 - 聂微东
A
About on SuperTechFans
大猫的无限游戏
大猫的无限游戏
P
Proofpoint News Feed
Martin Fowler
Martin Fowler
博客园 - 【当耐特】
S
SegmentFault 最新的问题
Blog — PlanetScale
Blog — PlanetScale
酷 壳 – CoolShell
酷 壳 – CoolShell
G
Google Developers Blog
I
InfoQ
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
GbyAI
GbyAI
B
Blog
Engineering at Meta
Engineering at Meta
V
V2EX
Hugging Face - Blog
Hugging Face - Blog

博客园 - USEGEAR

学习unigui【48】lucksheet表格的显示object 学习使用 处理Python对象和列表【5】 学习使用:创建 Python 可调用的 Delphi 函数【4】 学习使用TPythonDelphiVar组件 数据交换Delphi与Python传值【3】 学习使用 数据交换 Delphi 与 Python 传值【2】 学习使用 Python4Delphi 是什么【1】 学习unigui【47】扫码安装apk 学习unigui【46】让客户端浏览器可以选下载你的apk 学习unigui【45】UnimDatePicker等按钮汉化崩溃 学习unigui【43】如何和控件打交道 学习unigui【42】UnimDatePicker的使用 学习unigui【41】htmlframe的交互现象 学习unigui【40】加入监控墙-1 头大的内存泄漏 学习unigui【39】单独文件在ms win server 上执行的坑 学习unigui【38】重新认识UUNIGUI--为什么这样快? 站在“架构与性能”层面重新审视 学习unigui【37】nginx的反向代理 ,程序中的重新定向 学习unigui【36】把数据导航放在Unidbgrid脚中 学习unigui【35】dbgrid字段宽度自适应 KingSADA的工业历史数据库的访问
学习unigui【44】如何和uinHTMLFrame打交道
USEGEAR · 2026-01-12 · via 博客园 - USEGEAR

一个极简、可复用的“UniGUI(M) + HTMLFrame/iframe 通信桥模板”。只保留关键段落:装桥、推数据、收事件、延迟关闭。你以后做水质、PLC、Luckysheet、任何 iframe UI,都按这个骨架套。


0)命名约定(统一协议)

  • 前端 → 父页面:{type:'ui_event', name:'close'|'refresh'|'save', payload:{...}}

  • 服务器 → 前端:{type:'ui_render', name:'render', payload:{...}}

  • ACK:{type:'ui_ack', name:'close'}(可选但强烈建议)


A) iframe 页面(xxx.html)— 最小模板


B) Delphi:Frame(承载 HTMLFrame/iframe)— 最小模板

1)核心字段与公开方法(骨架)


2)InitTemplate:注入 iframe + 装桥 + 绑定目标


3)InstallBridgeOnce:父页面监听 postMessage → ajaxRequest

这里最关键:把 iframe 的 {type:'ui_event',name:'close'} 转成 ajaxRequest(UnimHTMLFrame1,'ui_close',[])


4)BindTarget:目标固定为 UnimHTMLFrame1(最稳)

不玩 JSId/Ext.getCmp 那套。目标就是 UniGUI 组件对象本身(通过 ComponentQuery 找到 UniGUI 的 ajax target)。

你已经验证“目标对象乱找”会出 Object not found,所以这里用 UniGUI 自己的“ajax target”方式绑定——最稳是:直接把 target 存成 UnimHTMLFrame1 的客户端对象引用。在 UniGUI 前端,组件一般都有 UnimHTMLFrame1.JSName 可直接引用;如果你环境里没有,就用 ComponentQuery 通过 UnimHTMLFrame1.JSId 找到 UniGUI 包装对象。

用 JSId 找对象(但找的是 UniGUI 组件,不是随便 Ext 控件):


5)服务器端收事件:绑定到 UnimHTMLFrame1.OnAjaxEvent


6)延迟关闭(避免 session list object not found)


7)推数据给 iframe(RenderToIframe)


C) 你要记住的“5 个硬规则”(像螺丝刀一样随手用)

  1. iframe 只负责 UI,不碰 UniGUI:只用 postMessage

  2. 父页面只干一件事message → ajaxRequest

  3. ajaxRequest 的 target 必须是“UniGUI session 对象”,不能乱拿 Ext id

  4. 关闭/销毁类动作必须延迟(Timer),避免 session list 报错

  5. 所有调试先看 ACK 和 bind log:ACK=消息到父;bind=目标存在;两者都对才可能进 Delphi


这个模板你可以直接复制成一个新的 TUniFrame_UiBridge,以后 PLC/水质/报表/编辑器都套它。你要我把它整理成你项目里能直接编译的完整 unit(含 dfm 绑定点、具体 uses、最少依赖)也可以。

更健康的策略(你现在已经走到这条路上了)

  1. 页面内部交互:局部闭环
    事件落点固定在本页面的 UnimHTMLFrame(或本 Form),逻辑清晰、可复用、可预测。

  2. 真正的全局规则:Delphi 端做“服务端真相源”
    统一退出、权限校验、状态栏信息、全局状态机——这些都放在服务器端(MainModule/ServerModule/统一服务类),前端只是“显示结果”和“提交请求”。

  3. 跨模块通讯:用“服务器端事件/状态”而不是“前端广播”
    比如:登录状态变化、权限变更、强制退出
    → 服务器端更新状态
    → 当前页面下一次交互/定时心跳/必要时推送时再响应(你也可以做很轻量的轮询或服务器推送,但那是另一套专门机制)

你可以记一个简单原则

前端不要当操作系统。
前端是 UI 和输入层;全局一致性、权限、生命周期这些“系统级规则”,交给 Delphi 端。

这条原则会让你未来做 Luckysheet、ECharts、各种 HTMLFrame 都更稳:每个页面都是一个小闭环,服务器端是唯一权威的大脑。