WebView2 是越来越香了。 WebView2 不但是 Win11 自带的系统组件,Win10 也已经自动推送安装。即使是少量没有安装 WebView2 的系统 —— 使用 aardio 中的 web.view 也会自动安装( 不需要写任何代码 )。 我用 WebView2 开发了很多项目,不得不说 WebView2 稳定可靠、性能强悍,接口简洁,是真的让人省心。 ▶ htmx.js 这里介绍一个适合用于 WebView2 的极简前端组件 htmx.js ,这个组件最大的特色就是简单,一学就会,也很容易理解。 我们正常浏览一个网页的过程是在浏览器里输入网址,向 HTTP 服务器发送请求。然后服务器返回 HTML 代码,浏览器显示页面。 但是 htmx.js 脑洞大开,让网页上的每一个 HTML 节点都可以向服务器发送请求并获取 HTML,并实时更新页面上指定的节点。而且不需要写任何 JavaScript 代码。 ▶ 起步首先我们打开 aardio ,创建 WebView2 工程并选择 htmx.js 模板: 生成的工程如下: 点『运行』可直接测试效果,点『发布』可生成独立 EXE 文件 。 在工程管理器中右键点『网页』弹出菜单,然后点『用外部编辑器打开』,如果安装了 VS Code 会使用 VS Code 打开网页目录。 在 VS Code 中点击并打开 index.html 源码: ▶ htmx.js 基础
打开 index.html ,先看最简单的 htmx.js 示例: 注意看凡是 "hx-" 前缀的属性都是用于 htmx.js 。 hx-trigger 用于指定在什么事件发生时触发 HTTP 请求,例如: 表示在 click 单击事件发生时触发请求。这里使用的是标准的事件名,例如按键 keydown ,放开按键 keyup,鼠标进入 mouseenter 鼠标离开 mouseleave 等等。 而事件名后还可以指定修饰符,例如只允许触发一次的 once : 其他修饰器: 下面的 HTML 使用了多个事件修饰器: 这表示在按键放开( keyup ),文本框的内容发生改变( changed )时触发,并且延时 500 毫秒再发送请求。 hx-get 则指定要请求的是哪个后端页面,例如: 表示事件触发时,请求 "/api/index.aardio" 这个页面。因为 aardio 在启动 SPA 应用时自动指定了后端根目录为 "/web",所以实际请求的是 "/web/api/aardio" 。 而 hx-swap 则指定要将返回的 HTML 写入到哪里,"innerHTML" 指定是更新网页节点内部 HTML,"outerHTML" 指定替换目标网页节点的全部 HTML ,其他还有 "afterbegin" , "beforebegin" , "beforeend" , "afterend" , "none" 。这些看名字就知道是什么作用,就不解释了。 hx-target 属性用 CSS 选择器指定要写入的网页节点,例如: 指定服务器返回的 HTML 写入 id 为 "info-div" 的节点。如果省略 hx-target 属性表示写入目标是当前节点自身。 hxmx.js 在更新 HTML 时,如果发现新旧 html 中有 id 相同的元素会进行优化并平滑显示。 看到这里,htmx.js 您已经会用了。 虽然 htmx.js 文档里有更多花式用法,但一般可能用不上。有些事搞太复杂了也不一定是好事。 ▶ htmx.js + aardio 后端aardio 提供了嵌入式 HTTP 服务器,可以直接使用 aardio 代码写网页,支持与 PHP 类似的模板语法。 aardio 的模板语法很简单,aardio 代码写在 <? ?> 内部,而 HTML 代码写在 <? ?> 外部就可以了。实际上 <? ?>外部的代码被转换为了 aardio 中 print 函数的参数。 例如服务端有下面的 aardio 代码: 运行后会自动转换为纯 aardio 代码如下: 在 HTTP 后端中,print 函数实际上就是指向用于向 HTTP 客户端输出数据的 response.write() 函数。 在 HTTP 后端有两个最常用的对象,request 对象包含了所有 HTTP 请求信息,而 response 对象为 HTTP 响应对象,用于向客户端发送数据。 打开 aardio 自带「工具 > 库函数文档」,点击 fastcgi.client 的文档可以查看 request, response 对象的所有属性与方法。aardio 中的所有 HTTP 服务端实现都统一兼容 fastcgi.client 文档规定的 request, response 用法。 也可以参考 aardio 开始页的 《 aardio 网站开发、FastCGI开发入门教程 》。至于 aardio 模板语法,请参考 《 aardio 语法与使用手册 > aardio 语言 > 模板语法 》 aardio 的模板语法不仅仅可以用于写 HTTP 后端,也不仅仅是可以用于输出 HTML,实际上可以用于生成任何字符串。aardio 中的很多功能都支持这种模板语法,例如运行时编译 C# 代码就支持用 aardio 模板语法生成 C# 代码。另外 aardio 提供 string.loadcode() 函数可以直接解析 aardio 模板并返回字符串。 ▶ htmx.js 指示动画,aardio 后端线程这里要注意,上面范例工程默认导入的 HTTP 服务器是: 这是一个多线程的 HTTP 服务端,每次被请求执行的 aardio 代码都是在后台线程中运行。aardio 多线程开发要注意的是每个线程都运行在独立的环境,全局变量是相互隔离的,这个限制实际上让 aardio 的多线程开发更简洁,坑更少,具体请参考 aardio 自带「范例程序 > aardio 语言 > 多线程」。 如果改为 wsock.tcp.asynHttpServer 则是单线程异步的 HTTP 服务器。 下面我们仍然使用默认的 simpleHttpServer 。多线程的好处是耗时操作不会卡界面。后端在进行耗时操作时,网页前端通常需要显示一个动画,htmx.js 做这事就很简单。 我们只要简单的修改一下前面讲过的网页代码如下: 主要是增加了 hx-indicator 属性,该属性的值用一个 CSS 选择器指定了发送 HTTP 请求时要显示的 HTML 元素,这里指定的是 id 为 "indicator" 的元素。 实际上我们可以自定义这个请求动画的样式,我们打开样式文件 index.css 添加下面的样式: 在发送请求时,网页上被设定的指示元素会自动添加 CSS 类 "htmx-request",HTTP 请求结束会移除该类。 然后我们打开对应的 aardio 后端代码 /web/api/index.aardio ,输入以下代码:
上面的代码的作用是:如果收到 GET 请求,线程就休眠 2 秒以模拟耗时操作。然后输出当前时间。 我们运行一下看看效果: ▶ 请求参数
htmx.js 提交请求的节点如果是一个表单控件,只要指定 name 属性 —— 就会自动以该名字发送请求参数,参数值就是控件的值。 如果提交请求的节点是表单,则 HTTP 请求参数为表单内所有控件的值。 也可以在节点的 hx-vals 属性中用一个 JSON 对象指定请求参数,例如网页这样写: aardio 后端就可以使用: 取到 HTTP 请求参数 myval 的值。 如果使用 POST 发送请求,例如: 那么 aardio 后端可以使用 取到 HTTP 请求参数 myval 的值。
在 aardio 后端使用:
可以取到 GET 或 POST 发送的 myval 参数值。 hx-vals 还可以通过加上 javascript: 或者 js: 前缀后使用 JS 对象返回请求参数,例如: ▶ web.form 也玩 htmx.js
有趣的是 web.form 也可以支持 htmx.js 。 web.form 是基于系统自带的 IE 内核控件,注意系统虽然删除了 IE 浏览器,但 IE 控件属于系统组件,Windows 有说明该控件不会被移除。IE 控件的好处是从 XP 到 Win11 所有操作系统都自带。 而且 IE 控件很轻量,与本地程序交互的接口也非常方便。Win10 ,Win11 自带的是 IE11 内核,写写一般的网页还是很好用的。至于 Win7 —— 因为只有极低的份额,一般软件不用考虑。 htmx.js 最后一个支持 IE 11 的版本是 1.6.1 ,这个足够用了。前面说过我们需要的只是局部请求刷新的功能,其他功能我们用不上,所以追新无意义。 首先我们打开 aardio 工程向导,选择「 Web 界面 > Web Form 」然后创建工程即可,新版工程模板默认就是使用 htmx.js 。 其他 HTML 代码写法与前面介绍的 WebView2 基本一样。不过 web.form 本就支持 EXE 内嵌资源文件,所以默认并不会启动 HTTP 服务器,需要多写几句代码。 打开工程的 webPage.aardio 源码: 可以看到源码中是如下启动 HTTP 服务器的: 我并没有把这几句代码封装到 wb.go() 函数中。 有些新手总以为代码越少越好,其实并非如此,有时候多写几句更容易看清楚代码的思路,更容易理解我们正在使用的技术。 下面我们看下 web.form + htmx.js 范例的运行效果: 上面示例程序的主窗口是使用 win.ui.tabs 做的,只有其中一个标签页用到了网页。 其实一般桌面软件的界面并不是一定要全部使用网页实现。有时候我们将界面中适合用网页呈现的部分用网页做,可能会更好。 我们在使用任何技术时,都要考虑一下适不适合。没有一样技术能适合做所有的事,多个选择总是好事
|