WindowTem 模板
WindowTem 是 Window 之上的糖衣基类,组合一个 shared_ptr<Window>,对标 Electron TS 版 WindowTem。省去手写 RPC 注册样板:声明式 emit 白名单 + 内置窗口控制槽 + 虚钩子。
为什么用它
裸 Window 用法下,每个窗口子类都要手写:
- 重复绑
min/close/topic/ 拖动等窗口控制槽 - 手动管 emit 白名单(哪个通道能往 JS 推)
- 手动等页面加载完再初始化
WindowTem 把这些内置:构造 + start() 两行,样板消失。
内置槽
WindowTem 构造时自动绑定两个固定通道,前端直接调:
js
bridge.call('handleWindowBtn', { type: 'min' }); // min / close / topic(置顶切换)
bridge.call('moveWindow', { x, y }); // frameless 自绘拖动配合 无边框自绘窗口 一套即用。
最小用法
cpp
auto win = app.createWindow(Window::opts().title(L"app").size(800, 600));
auto tem = std::make_shared<webview::WindowTem>(win);
tem->emits({"dataReady"}); // 声明可往 JS 推的通道
tem->on("greet", [](webview::json a) {
return webview::json{{"msg", "hi " + a.at("name").get<std::string>()}};
});
tem->start(); // 触发 initBridge() + 页面加载完成→onMounted()emit 白名单
emits({"ch1","ch2"}) 声明允许 send 的通道。未声明的 send 抛异常(严格模式,对标 TS):
cpp
tem->emits({"dataReady", "progress"});
tem->send("dataReady", payload); // OK
tem->send("xxx", payload); // throw这防手滑发未约定通道。
继承式(推荐)
把槽集中到子类 initBridge,对标 TS 子类:
cpp
class MainWindow : public webview::WindowTem {
public:
using webview::WindowTem::WindowTem;
void initBridge() override {
emits({"downloadCb"});
on("getWindowInfo", &MainWindow::getWindowInfo);
on("saveProject", &MainWindow::saveProject);
}
private:
webview::json getWindowInfo() { return /* ... */; }
void saveProject(webview::json data) { /* ... */ }
};
auto w = std::make_shared<MainWindow>(win);
w->start();逐个 bind
WindowTem(底层 Window)不支持 TS 那样的字符串反射 this[name] 自动绑定。槽必须在 initBridge 里逐个 on(name, &Cls::method) 显式绑。
虚钩子
| 钩子 | 调用时机 |
|---|---|
initBridge() | start() 触发,绑槽时机 |
onMounted() | 页面 DidFinishLoad 后,DOM/CSS 已就绪 |
cpp
void onMounted() override {
// 页面就绪,可安全 call JS / 注入数据
send("dataReady", initialData());
}start() 幂等,调多次安全。
生命期约束
销毁顺序
WindowTem 必须先于其 Window 销毁。start() 注的 DidFinishLoad 回调捕获 this,EventBus 无 unsubscribe——若 Window 先没,回调悬空。
即:先释放 WindowTem 的 shared_ptr,再释放 Window。
超时
构造第二参设 call 超时(毫秒),默认 300000(对标 TS TIMEOUT_TIME):
cpp
auto tem = std::make_shared<WindowTem>(win, 5000); // 5s 超时