{"id":18356519,"url":"https://github.com/lbwa/qwebchannel-bridge","last_synced_at":"2025-04-06T12:32:18.215Z","repository":{"id":39423413,"uuid":"199392741","full_name":"lbwa/qwebchannel-bridge","owner":"lbwa","description":"🌉How to intergrate @qt qwebchannel with @vuejs","archived":false,"fork":false,"pushed_at":"2022-12-11T02:11:49.000Z","size":1901,"stargazers_count":30,"open_issues_count":6,"forks_count":3,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-15T00:09:08.080Z","etag":null,"topics":["hybrid-app","js-bridge","qt","qt5","qwebchannel","qwebengine"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lbwa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-07-29T06:33:08.000Z","updated_at":"2025-03-11T15:23:17.000Z","dependencies_parsed_at":"2023-01-26T14:15:21.537Z","dependency_job_id":null,"html_url":"https://github.com/lbwa/qwebchannel-bridge","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lbwa%2Fqwebchannel-bridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lbwa%2Fqwebchannel-bridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lbwa%2Fqwebchannel-bridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lbwa%2Fqwebchannel-bridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lbwa","download_url":"https://codeload.github.com/lbwa/qwebchannel-bridge/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247484474,"owners_count":20946388,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hybrid-app","js-bridge","qt","qt5","qwebchannel","qwebengine"],"created_at":"2024-11-05T22:10:34.521Z","updated_at":"2025-04-06T12:32:16.505Z","avatar_url":"https://github.com/lbwa.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eQWebChannel bridge\u003c/h1\u003e\n\nThis is an integration approach for `QWebChannel` with `Vue.js v2`, consisted of a `message broker` layer.\n\n[中文指南](https://set.sh/post/190728-intergrate-qwebchannel)\n\n## Prerequisites\n\n`Qt` side should provide one or more `QObject` which include all information shared with `JS` side.\n\n1. A `Cpp` function named `emitEmbeddedPageLoad`\n\n   ```cpp\n   class WebBridge: public QObject {\n     Q_OBJECT\n     public slots:\n       void emitEmbeddedPageLoad() {\n           QMessageBox::information(NULL,\"emitEmbeddedPageLoad\", \"I'm called by client JS!\");\n       }\n   };\n\n   WebBridge *webBridge = new WebBridge();\n   QWebChannel *channel = new QWebChannel(this);\n   channel-\u003eregisterObject('keyNamedContext', webBridge);\n   view-\u003epage()-\u003esetWebChannel(channel);\n   ```\n\n1. In `JS` side, you should provide a init function when `QWebChannel` initialized.\n\n   ```ts\n   new QWebChannel(window.qt.webChannelTransport, function(channel) {\n     const published = channel.objects.keyNamedContext\n     Vue.prototype.$_bridge = published\n\n     // This function calling will notify Qt server asynchronously\n     published.emitEmbeddedPageLoad('', function(payload: string) {\n       // This payload has included dispatcher name and its parameters.\n       dispatch(payload)\n       console.info(`\n           Bridge load !\n         `)\n     })\n   })\n   ```\n\n   **Advance**: You can also create a process like [these implementation](./src/bridge/index.ts#L73-L106) for function calling or properties reading with abstract `namespace`.\n\n1. `dispatch` function should include all navigation logic.\n\nOnce `QWebChannel` initialized, `dispatch` will be invoked when `Cpp` function named `emitEmbeddedPageLoad` return a value \u003csup\u003e[async notification](https://doc.qt.io/qt-5/qtwebchannel-javascript.html#interacting-with-qobjects)\u003c/sup\u003e. `dispatch` function would play a **navigator** role in `JS` side.\n\n## How to navigate\n\n1. In `Qt` side, all entry point should be based on **root** path - `https://\u003cYOUR_HOST\u003e/`. All navigation will be distributed by `JS` side (`vue-router`, a kind of front-end router) rather than `Qt`. `Qt` side would has more opportunities to focus on other business logic.\n\n   - When `Qt` side receives a initial message from `JS` side, it should return a value which syntax should be like:\n\n     ```ts\n     interface InitialProps {\n       type: string\n       payload: any\n     }\n     ```\n\n     ```ts\n     // Actual value\n     {\n       type: [JS_SIDE_DISPATCHER_NAME],\n       payload: [OPTIONAL_PAYLOAD]\n     }\n     ```\n\n   `type` property will be used to invoke `dispatcher` in the [dispatchersMap](./src/config/bridge.ts), then `payload` property including any messages from `Qt` side will passed `dispatcher`. `dispatcher` in the [dispatchersMap](./src/config/bridge.ts) plays a `navigator` role in front-end, and developer should add navigation logic into here. This is all secrets about front-end navigation without `Qt` routing.\n\n   Above all process has described how to initialize `Vue.js` app in the `QWebEngine`, and how navigation works in the `Vue.js` with `QWebEngine`.\n\n1. Be careful any external link and redirect uri from any external web site like `Alipay` online payment links. If you want to respect any redirect uri and prevent navigation from above `dispatch` function, you **MUST** provide **non-root** redirect uri (eg. `https://\u003cYOUR_HOST\u003e/#/NOT_EMPTY_PATH`). You can find more details from [dispatch function here](./src/bridge/helper.ts).\n\n## How to push message from JS side\n\nIf you want to push messages from `JS` side to `Qt` side, you can invoke the mapping of `Qt` methods in `JS` side directly:\n\n```ts\nchannel.object[QObjectJSMappingKey].methodNameMappingFromQtSide(\n  payload,\n  callback\n)\n```\n\nEnhance: the following logic is based on [these implementation](./src/bridge/helper.ts#L35-L59):\n\n```ts\n// A QObject named `QObjectJSMappingKey` (as an abstract namespace) in Qt/JS side\n// in the vue instance\nthis.$$pusher.QObjectJSMappingKey({\n  action: 'QT_QOBJECT_KEY',\n  payload: 'CALLING_PAYLOAD'\n})\n```\n\n## How to push messages from Qt side\n\n[Qt signal listener mechanism](https://doc.qt.io/qt-5/qtwebchannel-javascript.html#overloaded-methods-and-signals) is a kind of good solution for communicate from Qt side to JS side. You may be wondering why we don't use signal mechanism directly to handle first frontend navigation? Because Qt side never known when frontend router is available until JS side push `loaded` message to Qt side positively.\n\n```cpp\nclass WebBridge: public QObject {\n  Q_OBJECT\n  public slots:\n    void emitEmbeddedPageLoad();\n\n  // define your own signal\n  signals:\n    void signalMessageFromQt(const QString \u0026str);\n};\n```\n\nAlways define all available signal listeners in [config/bridge.ts](./src/config/bridge.ts#L32-L36):\n\n```ts\ninterface SignalCallbacks {\n  [targetSignal: string]: Function\n}\n```\n\nAll signal would be handled automatically by [these codes](./src/bridge/helper.ts#L70-L84).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flbwa%2Fqwebchannel-bridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flbwa%2Fqwebchannel-bridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flbwa%2Fqwebchannel-bridge/lists"}