{"id":18739014,"url":"https://github.com/gaubee/hqml","last_synced_at":"2025-11-18T11:30:18.720Z","repository":{"id":149112310,"uuid":"55283881","full_name":"Gaubee/hqml","owner":"Gaubee","description":"Hpyer Qt Modeling Language. Run on ES3","archived":false,"fork":false,"pushed_at":"2016-04-09T15:49:33.000Z","size":501,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-12-28T17:44:43.516Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/Gaubee.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,"governance":null}},"created_at":"2016-04-02T07:50:16.000Z","updated_at":"2021-12-18T09:35:08.000Z","dependencies_parsed_at":"2023-04-26T01:02:43.696Z","dependency_job_id":null,"html_url":"https://github.com/Gaubee/hqml","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/Gaubee%2Fhqml","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gaubee%2Fhqml/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gaubee%2Fhqml/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gaubee%2Fhqml/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Gaubee","download_url":"https://codeload.github.com/Gaubee/hqml/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239616143,"owners_count":19668993,"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":[],"created_at":"2024-11-07T15:32:26.019Z","updated_at":"2025-11-18T11:30:18.665Z","avatar_url":"https://github.com/Gaubee.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# HQML\n\n## HQML是什么？\n\nHQML（**Hpyer** Qt Modeling Language）属于QML的一个超集 ~~，目前QT5.*中运行的是ES5的JS，HQML使用了更高级的Parser，是可运行ES6+的代码（语法上支持，如果需要API支持，则需引入Shim）~~。\n\nHQML是初衷和QML一致，是一个用于高效快速开发应用界面的标记语言。而HQML则是针对Web端这个方向做了大量的支持。也就是说HQML面向的并不是QtQuick这个框架，而是更青睐于前端开发者的思路写法。\n\n## 为什么开发HQML？\n\n在我以前开发第一代MV*框架的时候，我在View层采用了和Emberjs类似的，也即是Handlebar那种风格。因为我更喜欢HandleBar的灵活性，使用者只需要知道有`{{if、else、each}}`这类语法控制流程即可，而插值绑定则是可以写到任意的地方，包括节点内的文本，节点内的属性等等。\n然而在我所观察的框架使用者中发现，这些使用者其实只是对于数据绑定以及数据管理这方面满意，其它的方面，比如界面开发等等，依旧需要使用html+css这两门语言来进行混合开发，其效率与可用性依旧要依赖于团队的开发能力，而且业界内并没有一个统一的标准，使得前端的开发模式越来越混乱。\n\nWeb开发也远离了jQ的那个只要一个`jquery.*.js`+`$.run_plugins()`的统治时代。\n\nGoogle的Polymer试图统一这一个标准，而浏览器的支持不如人意，我在试用的时候（2016年初）发现Bug重重，而且从去年（2015）的IO大会发布1.0版本后，官方的更新与改进并不多。使用者更是寥寥无几。\n\nReact独树一帜，也正因如此，并不是每一个人每一个团队都适合使用。\n\n而在学习使用QML的过程中，我发现QML更适合做为Web App的界面开发语言，且不说其语法特性很容易让前端开发人员接受，QML的声明及绑定对于界面的开发来说是一个很强大的利器，在书写HTML的数据绑定以及带计算能力的CSS的时候，QML都是信手拈来。这也是以往开发MV*框架所不能解决的痛点：\n1. 以往的MV*框架中，为了给HTML语言增加数据绑定功能，不得不在HTML基础上增加一些标识或者拓展一些属性，也正因为是基于HTML进行拓展，所以开发者无法在HTML页面上使用多种HTML语法。也就导致了开发者的技术堆栈必须一致，从而引发在升级技术的是时候成本过高。\n2. CSS需要聪明（或者说鬼才？）的写法才能实现现代化动态Web页面的设计。由于CSS的出发点是描述一个局部的自我的布局，配合**@media标签**和**百分比布局**等以及兼容性不是很好的**计算属性**才能实现比较通用的响应式（就等于一条布局逻辑必须分开到不同的地方写，而这条布局逻辑在程序员的脑子里面只是一个if-else的逻辑），而使用@media的后果就是CSS代码的冗余，有时候网站的浏览者不得不下载其它屏幕尺寸的样式文件，否则就需要工程师做大量的优化。然而并不是每一个团队都愿意做的，所以你经常可以看到一个以百K为单位的css文件（PS：现在WebApp的数据是JS数据动态绑定HTML-Template，所以HTML的代码量得到了改善，现在不会看到一个WebApp里头一个HTML文件动辄千行的情况。）。总之，现在的CSS开发者可以很直接的感受到CSS语法表达动态布局能力上的不足，至少没法真的做到**直观地和思维逻辑同步**，即便是很熟悉CSS的开发者，也需要将布局翻译成难以阅读的CSS，然后用冗长的繁杂的Class去做分类等。\n\n这也是我为什么要将QML作为新一代框架的开发语言，应为它能一站式的解决前端开发人员大量的痛点。\n\n## HQML兼容QML吗，能运行在Qt上吗？\n\n理论可以，但不处在前期开发的计划中，后期如果有精力或者自己有需求的情况下会加上。\n\n容我解释一番：一开始，这个项目的命名是QML2JS，[思路在这篇文章里面：qml2js.md](./qml2js.md)，目标就是在QtQuick的平台上做一个QML-HTML包，然后在Web端也开一个包，接着就使用qmlweb来运行qml，qmlweb是打算把整个QtQuick的框架完全引入Web，我不是很赞同的qml2web的做法与方向。\n\n## HQML的工作原理\n\n如何运行ES5代码？如何做到QML那种标记语言声明绑定？\n\n我在这里讲一下原理，这点很重要，要知道它能运行在ES3上。而运行的原理，就是将AST-Tree解析成类似Lisp语言（比如1+1，会解析成：binary(\"+\",1,1)），使得RunTime能够控制每一行代码的运行，从而实现ES5中Getter、Setter等纯ES3语法不能完全模拟的功能。\n\n开发者所写的HQML代码，最终编译成AST-Tree后才能运行在Web的RunTime上，而不是直接在网页上解析并运行一个QML脚本，除非你在网页上直接嵌入一个Parser。至于这个AST文件的大小？放心，肯定比你用：某框架+JS+HTML+CSS的体积来的小，而且RunTime的体积也足够小，能轻松运行。\n\n也许你会担心这种使用JS2JS代码的效率，请放心，这是可以在RunTime层面进行优化的（比如：在不提供evalQML的前提下，所以可以在一些没有被其它 计算属性 所引用的计算 的属性上做优化，将其编译成一个原生的底层的Getter函数，以原生的效率来运行。再比如：后期工作中也会把RunTime的部分代码在支持webassembly的平台上编译成字节码来加速运行，甚至会给出一个AST-TO-JS的ASM版本来实现更快的解析）。而且还提供底层的接口，让用户可以书写原生的JS代码模块来加速运行一些计算量大、或者通过RunTime暴露出来的手动实现一些绑定从而提升执行的效率。它是高度可优化的（PS:这基本不需要，除非一些开发者手写了动画并想把帧率以最小CPU的代价提升，而这点，我们会提供一个专门的Animation插件来实现：没有数据绑定动画属性会生成CSS，带数据绑定的则用JS控制，最终合成一个如同你手写CSS原生动画混合JS一样性能的动画，而代价仅仅是编译出动画的代码那个时间片）。\n\n而qmlweb也是JS RUN JS的原理，但二者的不同在于：qmlweb是使用即时运行的原理，而hqml使用一次编译后再执行。比如说有一个ListItem的组件，如果循环100次，qmlweb就要走100次walk，遍历100AST。而hqml则是一次性编译出一个big-function，100次循环也就只需要执行100次big-function。而new Function所带来的性能消耗，往往是伴随着下载时间段在执行。也就是网页不可用的期间，页面可能还在下载其它组件的时候，这时候充分利用CPU来执行编译。","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaubee%2Fhqml","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgaubee%2Fhqml","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaubee%2Fhqml/lists"}