今天给大家带来的主题是号称世界上最小的响应式 UI 框架,即 VanJS。话不多说,直接进入正题。
VanJS(缩写为 Vanilla JAVAScript)是一个基于纯 Vanilla JavaScript 和 DOM 的超轻量级、零依赖和特立独行(unopinionated)的响应式 UI 框架。使用 VanJS 编程会让开发者感觉很像 React。比如下面的 Hello World 代码:
// 可重用组件可以只是纯 vanilla JavaScript 函数
// 将第一个字母大写以遵循 React 约定
const Hello = () => div(
p("Hello"),
ul(
li("️World"),
li(a({href: "https://vanjs.org/"}, "VanJS")),
),
)
van.add(document.body, Hello())
// 或者,你可以这样写:
// document.body.AppendChild(Hello())
开发者可以使用 VanJS 提供的在线转换器将任何 html 片段转换为 VanJS 代码。 VanJS 还可以通过更自然的 API 帮助开发者管理状态和 UI 绑定:
const Counter = () => {
const counter = van.state(0)
// state表示状态
return div(
"❤️ ", counter, " ",
button({onclick: () => ++counter.val}, ""),
button({onclick: () => --counter.val}, ""),
)
}
van.add(document.body, Counter())
VanJS 的愿景是成为 UI 的脚本语言,就像 bash 是终端的脚本语言一样。 VanJS 使前端工程师、后端工程师、系统工程师、数据科学家和任何其他人都能够构建全面的用户界面。
开发者可以随时随地在任何设备上使用 VanJS 进行编码,甚至在智能手机上!VanJS具有以下显著特点。
VanJS 提供了 React 的所有优点,包括:声明式 DOM 组合、可重用组件、相对状态绑定。但 VanJS 不需要 React、JSX、转译、虚拟 DOM 或任何隐藏逻辑。 一切用户界面都是用简单的 JavaScript 函数和 DOM 构建。
即使没有状态和状态绑定,开发者也可以构建交互式网页, VanJS 用于 DOM 组合和操作的灵活 API:标记函数和 van.add。
const StaticDom = () => {
const dom = div(
div(
button("Dummy Button"),
button(
{onclick: () =>
van.add(dom,
div(button("New Button")),
div(a({href: "https://www.example.com/"}, "This is a link")),
)
},
"Button to Add More Elements"),
button({onclick: () => alert("Hello from VanJS")}, "Hello"),
),
)
return dom
}
无需任何安装、无需配置、无需第三方依赖、无需转译、无需 IDE 设置。要使用 VanJS 只需在脚本或 HTML 文件中添加一行代码即可开始编码。
import van from "./van-0.11.9.min.js"
// 要在没有 ES6 模块的情况下进行编码,可以下载打包版本 van-0.11.9.nomodule.min.js
// 并将以下行添加到 HTML 文件中:
<script type="text/javascript" src="van-0.11.9.nomodule.min.js"></script>
VanJS 让开发者可以专注于应用程序的业务逻辑,而不是陷入框架和工具的泥潭。
VanJS 是 Vanilla JavaScript 和 DOM 之上的一个非常薄的封装层,几乎不足以使 DOM 操作和状态绑定与 React 一样符合人体工程学(如果不超过),VanJS 将大部分工作委托给以本机代码实现的标准浏览器 API。
因此,VanJS 的包大小仅为 1.2kB,比大多数流行的 UI 框架小 100 多倍,只有 Preact 的体积1/10,如下图:
完美的实现,不是在没有什么可以添加的时候,而是在没有什么可以去掉的时候
VanJS 为 TypeScript 提供一流的支持。 只需将相应的 .d.ts 文件与 .js 文件一起下载,开发者就可以利用首选的开发环境提供的类型检查、IntelliSense 和大规模重构。下面是不同文件的功能说明。
VanJS 非常强调框架的简单性。 API 中只有 4 个导出函数,感觉非常像 React。 因此,演练教程与完整的 API 参考相同,大多数开发人员可以在 1 小时内学会。
无需 JSX 的客户端、服务器端渲染的极简模板引擎,Mini-Van 是用于 DOM 组合和操作的超轻量级模板引擎。 Mini-Van 的最小包大小仅为 0.5kB,使开发者能够使用优雅且富有表现力的普通 JavaScript 代码构建全面的 UI。
Mini-Van 是 VanJS 的精简版,旨在提供一个基于纯 vanilla JavaScript 和 DOM 的超轻量级、零依赖、特立独行的 Reactive UI 框架。 与 VanJS 相比,Mini-Van 将 bundle 大小进一步降低到 0.5kB,并且可以在服务器端用作模板引擎。
Mini-Van 可以在服务器端用作模板引擎,为 HTTP 服务器渲染动态 Web 内容,借助于 NPM 包 mini-van-plate,可以在 Node.js 或 Bun 中使用。
目前服务器端集成有两种模式,即 van-plate 模式(基于文本模板,因此不需要 DOM 依赖)和 mini-van 模式(基于 DOM,因此需要 DOM 依赖)。
import http from "node:http"
import van from "mini-van-plate/van-plate"
const {a, body, li, p, ul} = van.tags
const hostname = '127.0.0.1'
const port = 8080
console.log("Testing DOM rendering...")
// 在控制台中生成`<a href="https://vanjs.org/">VanJS</a>`
console.log(a({href: "https://vanjs.org/"}, "VanJS").render())
const server = http.createServer((req, res) => {
res.statusCode = 200
res.setHeader('Content-Type', 'text/html; charset=utf-8')
res.end(van.html(
body(
p("Your user-agent is: ", req.headers["user-agent"] ?? "Unknown"),
p("Hello"),
ul(
li("️World"),
li(a({href: "https://vanjs.org/"}, "VanJS")),
),
),
))
})
server.listen(port, hostname, () =>
console.log(`Server running at http://${hostname}:${port}/`))
Mini-Van 也可以在 van-plate 模式和 mini-van 模式下与 Deno 一起使用。 Deno 模块已在 deno.land/x/minivan 发布。下面是van-plate模式代码:
import { serve } from "https://deno.land/std@0.184.0/http/server.ts"
import van from "https://deno.land/x/minivan@0.3.3/src/van-plate.js"
const {a, body, li, p, ul} = van.tags
const port = 8080
console.log("Testing DOM rendering...")
// 在控制台输出 `<a href="https://vanjs.org/">VanJS</a>`
console.log(a({href: "https://vanjs.org/"}, "VanJS").render())
console.log(`HTTP webserver running. Access it at: http://localhost:${port}/`)
awAIt serve(req => new Response(
van.html(
body(
p("Your user-agent is: ", req.headers.get("user-agent") ?? "Unknown"),
p("Hello"),
ul(
li("️World"),
li(a({href: "https://vanjs.org/"}, "VanJS")),
),
),
),
{
status: 200,
headers: {"content-type": "text/html; charset=utf-8"},
},
), {port})
在Mini-Van 模式下需要第 3 方 DOM 库来提供 Document 对象,下面是一个集成 deno-dom 的代码示例:
import { serve } from "https://deno.land/std@0.184.0/http/server.ts"
import { DOMParser } from "https://deno.land/x/deno_dom@v0.1.38/deno-dom-wasm.ts"
import van from "https://deno.land/x/minivan@0.3.3/src/mini-van.js"
const document = new DOMParser().parseFromString("", "text/html")!
const {tags, html} = van.vanWithDoc(document)
const {a, body, li, p, ul} = tags
const port = 8080
console.log("Testing DOM rendering...")
const anchorDom = a({href: "https://vanjs.org/"}, "VanJS")
// anchorDom is an HTMLAnchorElement
// 在控制台输出 `<a href="https://vanjs.org/">VanJS</a>`
console.log(anchorDom.outerHTML)
console.log(`HTTP webserver running. Access it at: http://localhost:${port}/`)
await serve(req => new Response(
html(
body(
p("Your user-agent is: ", req.headers.get("user-agent") ?? "Unknown"),
p("Hello"),
ul(
li("️World"),
li(a({href: "https://vanjs.org/"}, "VanJS")),
),
),
),
{
status: 200,
headers: {"content-type": "text/html; charset=utf-8"},
},
), {port})
要在客户端使用,需要下载最新版本的 mini-van-0.3.3.min.js 并将以下行添加到脚本中:
import van from "./mini-van-0.3.3.min.js"
如果要在不支持 ES6 模块的情况下进行编码,可以下载打包好的版本
mini-van-0.3.3.nomodule.min.js 并将以下行添加到 HTML 文件中:
<script type="text/javascript" src="mini-van-0.3.3.nomodule.min.js"></script>
本文主要和大家介绍号称世界上最小的响应式 UI 框架,即 VanJS。相信通过本文的阅读,大家对 VanJS 会有一个初步的了解。
因为篇幅有限,文章并没有过多展开,如果有兴趣,可以在我的主页继续阅读,同时文末的参考资料提供了大量优秀文档以供学习。最后,欢迎大家点赞、评论、转发、收藏!
https://Github.com/vanjs-org/van
https://vanjs.org/demo
https://vanjs.org/minivan
https://vanjs.org/start