大家好,我卡颂。
前端领域这几年涌现了很多新兴的前端框架,比如Qwik
、Svelte
、Astro
等。
这些框架多以「前端工程师」作为受众。
那么,以「后端工程师」作为受众的前端框架是啥样的,他与前者有什么区别呢?
介绍htmx
htmx
是一款在Django
技术栈最近比较热门的前端框架。
他的理念是 —— 「让网页回归HTML的本质,不再受JS束缚」。是不是很有web1.0
的风格?
他是怎么做到的呢?答案是:通过大量预制的自定义HTML
属性。
当你在页面中引入htmx.org.js
后,可以在HTML
中书写以hx-
开头的自定义属性。比如下面的代码:
<button
hx-post="/data"
hx-trigger="click"
>
点我请求data
</button>
点击按钮(hx-trigger
指定的click
事件)后,会向data
接口(hx-post
指定)发起post
请求。
那请求返回的数据如何显示呢?我们再增加2个自定义属性:
代码语言:javascript复制<button
hx-post="/data"
hx-trigger="click"
hx-target="#parent-div"
hx-swap="outerHTML"
>
点我请求data
</button>
hx-target
指代「返回的HTML结构」会被注入到哪里。这里会被注入到「id为parent-div的DOM」中。
hx-swap
指代「返回的HTML结构会以什么形式注入」。这里会直接替换「id为parent-div的DOM」。
如果hx-swap="innerHTML"
,则代表会以「id为parent-div的DOM」的innerHTML
形式注入。
如果要表达复杂的逻辑,需要结合很多自定义属性与属性值,比如下面的代码:
代码语言:javascript复制<input
type="text"
hx-get="/trigger_delay"
hx-trigger="keyup changed delay:500ms"
hx-target="#search-results"
placeholder="Search..."
>
当input
触发keyup
事件且值改变后,延迟500ms,向trigger_delay
接口发起请求,返回的HTML
结构被注入到「id为search-results的DOM」中。
与其说htmx
是一款前端框架,更贴切的说,他应该是一款「HTML自定义属性工具库」。
他将很多常见JS
交互逻辑收敛到自定义HTML
属性中,借此减少JS
代码量。
现代前端框架通常是「状态驱动UI」,而htmx
的理念是「过程驱动UI」(类似jQuery
时代编写页面的方式)。
如果希望引入状态,需要以插件的形式引入alpine-morph
。
相比于:
- React:基于
JSX
- Vue:基于模版语法
alpine
是一款基于HTML
的前端框架。
这意味着使用alpine
需要直接在HTML
中以自定义属性的形式书写状态(与Vue v1
类似)。所以,他能很好的融入htmx
的体系中。
比如下面这段代码是段结合htmx
与alpine
的HTML
,其中以hx-
开头的是htmx
属性,以x-
开头的是alphine
属性:
<div hx-target="this" hx-ext="alpine-morph" hx-swap="morph">
<div x-data="{ count: 0, replaced: false,
message: 'Change me, then press the button!' }">
<input type="text" x-model="message">
<div x-text="count"></div>
<button x-bind:style="replaced && {'backgroundColor': '#fecaca'}"
x-on:click="replaced = true; count "
hx-get="/swap">
Morph
</button>
</div>
</div>
这段代码包含了交互逻辑与前端状态,最重要的是:他是合法的HTML
(而不是JSX
或模版语法这样的DSL
),这意味着他能轻松的在前后端之间传递,并在前端展示。
交互逻辑守恒
本质来说,网页的最终消费品是HTML
与CSS
。开发者编写交互逻辑改变HTML
与CSS
。
前端工程师习惯在网页中通过JS
编写交互逻辑。
后端工程师习惯在后端编写交互逻辑。比如在htmx
中,请求返回的是HTML
结构,这部分「生成HTML的逻辑」是在后端controller
中实现的(而不是在前端通过JS
生成)。
除此之外,还有一部分交互逻辑是在后端「HTML模版」中产生的。下图是Django
中结合htmx
的后端模版代码示例:
不管交互逻辑在前端还是后端实现,也不管用哪种语言实现,他是一定需要实现的,也就是说「交互逻辑守恒」。
但是,交互逻辑在前端还是后端实现,对页面带来的影响是不同的。
对页面性能的影响
交互逻辑在前端实现的越多,意味着「越多的JS代码」,如果这部分代码是首屏渲染所需的,那意味着更差的FCP[1]指标。
如果这部分代码是后续交互所需的,那意味着更差的TTI[2]指标。
为了减少前端JS
资源对性能的影响,前端框架都在逐步向后迭代,比如Next.js
之于React
,Nuxt.js
之于Vue
。
新兴框架中的Astro
、Qwik
等也是类似思路。
而本文聊的htmx
作为后端主导的前端框架,本身的立足点就是后端的view
层,所以天生就是页面性能友好的。
总结
根据「交互逻辑守恒」,交互逻辑一定需要实现,不是在前端就是在后端。
传统来说,前端框架将交互放在前端,这会造成JS
资源变大,影响性能。
单纯从功能来讲,htmx
仅仅是个「HTML自定义属性工具库」,他将一部分交互收敛到自定义属性中,减少前端交互逻辑。
剩下的交互逻辑放在后端的view
(作为页面模版),或controller
(将HTML
作为接口返回值),以此减少前端JS
资源的体积。
对于页面交互复杂度不高,且是后端主导的项目(不想写JS
逻辑),相信htmx
会是不错的选择。
参考资料
[1]
FCP: https://web.dev/fcp/
[2]
TTI: https://web.dev/tti/