今天給大家帶來的主題是號稱世界上最小的響應式 UI 框架,即 VanJS。話不多說,直接進入正題。
1.什么是 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())
2.為什么選擇 VanJS?
VanJS 的愿景是成為 UI 的腳本語言,就像 bash 是終端的腳本語言一樣。 VanJS 使前端工程師、后端工程師、系統工程師、數據科學家和任何其他人都能夠構建全面的用戶界面。
開發者可以隨時隨地在任何設備上使用 VanJS 進行編碼,甚至在智能手機上!VanJS具有以下顯著特點。
沒有 React/JSX 的響應式編程
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,如下圖:
完美的實現,不是在沒有什么可以添加的時候,而是在沒有什么可以去掉的時候
TypeScript支持
VanJS 為 TypeScript 提供一流的支持。 只需將相應的 .d.ts 文件與 .js 文件一起下載,開發者就可以利用首選的開發環境提供的類型檢查、IntelliSense 和大規模重構。下面是不同文件的功能說明。
簡單易學
VanJS 非常強調框架的簡單性。 API 中只有 4 個導出函數,感覺非常像 React。 因此,演練教程與完整的 API 參考相同,大多數開發人員可以在 1 小時內學會。
3.VanJS 高級特性之 Mini-Van
無需 JSX 的客戶端、服務器端渲染的極簡模板引擎,Mini-Van 是用于 DOM 組合和操作的超輕量級模板引擎。 Mini-Van 的最小包大小僅為 0.5kB,使開發者能夠使用優雅且富有表現力的普通 JavaScript 代碼構建全面的 UI。
Mini-Van 是 VanJS 的精簡版,旨在提供一個基于純 vanilla JavaScript 和 DOM 的超輕量級、零依賴、特立獨行的 Reactive UI 框架。 與 VanJS 相比,Mini-Van 將 bundle 大小進一步降低到 0.5kB,并且可以在服務器端用作模板引擎。
服務器端:Npm 集成
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}/`))
服務器端:Deno 集成
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>
4.本文總結
本文主要和大家介紹號稱世界上最小的響應式 UI 框架,即 VanJS。相信通過本文的閱讀,大家對 VanJS 會有一個初步的了解。
因為篇幅有限,文章并沒有過多展開,如果有興趣,可以在我的主頁繼續閱讀,同時文末的參考資料提供了大量優秀文檔以供學習。最后,歡迎大家點贊、評論、轉發、收藏!
參考資料
https://Github.com/vanjs-org/van
https://vanjs.org/demo
https://vanjs.org/minivan
https://vanjs.org/start