大家好,我是Echa哥。
推薦一個(gè)輕量完備的開源前端框架:dagger.js:https://daggerjs.org
什么是 dagger.js
dagger.js 是一個(gè)基于 html 的描述式單頁應(yīng)用開發(fā)框架,通過在頁面 DOM 元素上添加語義化的指令來驅(qū)動(dòng)業(yè)務(wù)邏輯。從語法特性的角度來說,dagger.js 模板 + 指令的工作方式與 Angular/Vue 比較接近。
dagger.js 采用去組件去 api 設(shè)計(jì),沒有對第三方代碼或工具的依賴,模型簡單,易于理解。與當(dāng)前的主流前端框架相比,使用者的整體學(xué)習(xí)和使用成本更低。
使用 dagger.js,開發(fā)者將無須依賴于:
項(xiàng)目構(gòu)建過程
dagger.js 工作在瀏覽器運(yùn)行時(shí)當(dāng)中。只需要通過 script 標(biāo)簽引入框架源碼(release 版本 gzip 壓縮后約 20KB)即可輕松創(chuàng)建單頁應(yīng)用程序。dagger.js 對項(xiàng)目代碼結(jié)構(gòu)是非侵入式的,您可以以極小成本對歷史項(xiàng)目(即使是非單頁應(yīng)用程序)進(jìn)行漸進(jìn)升級。
包管理工具
dagger.js 內(nèi)部實(shí)現(xiàn)了一個(gè)運(yùn)行時(shí)模塊管理器,根據(jù)路由配置按需動(dòng)態(tài)加載和解析各類模塊,為您的應(yīng)用程序進(jìn)行極限瘦身。
第三方路由管理工具
dagger.js 內(nèi)置了基于 hash 的路由管理器。開發(fā)者無需引入額外的路由管理類庫。
數(shù)據(jù)狀態(tài)管理工具
dagger.js 倡導(dǎo)數(shù)據(jù)即狀態(tài)的技術(shù)理念。有別于 React/Vue 等框架單向數(shù)據(jù)流模型中對于 state/prop 對象的區(qū)分,dagger.js 的作用域數(shù)據(jù)由框架本身進(jìn)行維護(hù),并具有全域視圖響應(yīng)性,開發(fā)者不必為不同組件間的數(shù)據(jù)狀態(tài)同步而勞心費(fèi)神。
開發(fā)范式
不同于 React Hooks 和 Vue 的組合式 API 方案,dagger.js 提供了更加接近原生 JAVAScript 開發(fā)體驗(yàn)的心智模型。dagger.js 沒有設(shè)計(jì)任何框架相關(guān)的 “語法糖”,開發(fā)者編寫的腳本代碼只是普通的原生 JavaScript 函數(shù)。函數(shù)定義本身是上下文無關(guān)的,其觸發(fā)時(shí)機(jī)、調(diào)用參數(shù)以及副作用完全由調(diào)用者(指令)所決定。
dagger.js 中不存在組件(Component)實(shí)體的概念,指令是串接作用域數(shù)據(jù)(Model)和頁面視圖(View)的橋梁。換句話說,在 dagger.js 中,一切業(yè)務(wù)邏輯都以指令作為調(diào)用入口。某些特定指令可以在執(zhí)行上下文創(chuàng)建作用域數(shù)據(jù),而所有指令都可以作為作用域數(shù)據(jù)的消費(fèi)者。指令讀取或者修改作用域數(shù)據(jù),進(jìn)而觸發(fā)依賴收集或者頁面視圖的響應(yīng)式更新。
下文中我們將通過示例代碼來體驗(yàn) dagger.js 的工作模式。
創(chuàng)建作用域
在 dagger.js 中,我們可以通過生命周期指令 +loading 來創(chuàng)建作用域數(shù)據(jù):
+loading 指令在宿主元素(div)初始化時(shí)由框架觸發(fā)調(diào)用。它的副作用是,當(dāng)表達(dá)式的執(zhí)行結(jié)果是一個(gè)平凡對象時(shí),框架將依據(jù)此對象在當(dāng)前上下文創(chuàng)建出新的作用域數(shù)據(jù)。技術(shù)上說,這個(gè)作用域數(shù)據(jù)是指令返回平凡對象的代理對象。
作用域數(shù)據(jù)在宿主元素被銷毀時(shí)由框架自動(dòng)移除,無需開發(fā)者手動(dòng)管理。
指令
在 dagger.js 中,除去生命周期指令之外,還有兩種重要的指令類型:控制指令和事件處理指令。
兩種指令都可以自由讀寫在其聲明位置可見的作用域數(shù)據(jù),但是行為有所不同。
控制指令
控制指令在執(zhí)行過程中會收集參與計(jì)算的作用域變量字段,并在指令的依賴項(xiàng)發(fā)生變化時(shí)動(dòng)態(tài)觸發(fā)指令重新執(zhí)行。我們來看一個(gè)例子:
resetnumber" $value#input="a">
span>${ c } = ${ a } + ${ b }
${ d } = 2 * (${ c })
示例鏈接:https://codepen.io/dagger8224/pen/JjpJxzq
上例中,我們在 div 元素上聲明了控制指令 $watch 的兩個(gè)實(shí)例。其中編號為#1” 的指令依賴于作用域變量下字段 a 和字段 b,編號為#2 的指令依賴于作用域變量下字段 c。當(dāng)用戶修改 a 或 b 的值時(shí),將首先觸發(fā)指令 $watch#1 重新計(jì)算,更新字段 c 的值。c 值發(fā)生變化后再觸發(fā)指令 $watch#2 重新計(jì)算,進(jìn)而更新字段 d 的值。
除去 $watch 指令之外,dagger.js 還提供了更多語義化的控制指令,我們簡單列舉下這些控制指令的使用方法:
$checked 指令用于綁定宿主元素的選中狀態(tài),適用于類型為 radio 和 checkbox 的 input 元素,以及 option 元素。
$class 指令用于將表達(dá)式的內(nèi)容綁定到宿主元素的 class 屬性上。
$each 指令用于循環(huán)渲染具有相同視圖模板的數(shù)組,對象,或者其他可迭代變量。
$exist 指令用于切換宿主元素及其子級元素的存在狀態(tài)。
$html 指令用于在宿主元素下動(dòng)態(tài)創(chuàng)建子級元素。
$file 指令用于綁定用戶選擇的本地文件信息。
1
$selected 指令用于綁定宿主元素的選中值,適用于類型為 radio 和 checkbox 的 input 元素,以及 select 元素。
$style 指令用于綁定宿主元素的 style 屬性。
${ text }
$text 指令用于在宿主元素下動(dòng)態(tài)創(chuàng)建文本內(nèi)容。大多數(shù)情況下,我們也可以使用原地模板字符串(上例第二種方式)來創(chuàng)建動(dòng)態(tài)文本節(jié)點(diǎn),這樣更加簡單靈活。
$value 指令用于將表達(dá)式的內(nèi)容與 input 元素的 value 建立雙向數(shù)據(jù)綁定。
事件處理指令
與控制指令相比,事件處理指令的用法更加簡單。事件處理指令由用戶操作或系統(tǒng)事件觸發(fā)調(diào)用,在執(zhí)行過程中不會對作用域數(shù)據(jù)進(jìn)行依賴收集。我們來看一個(gè)例子:
alert(message)">click
上例中,button 元素上的 +click 指令聲明了一個(gè)鼠標(biāo)點(diǎn)擊事件處理函數(shù)。類似地,您也可以聲明其他的原生事件處理指令(+keyup,+mouseenter 等等),或者自定義事件處理指令(例如:+custom_event)。
接下來我們來看幾個(gè)指令的綜合示例:
指令綜合示例 1
下面的示例代碼演示了生命周期指令 +loading,+loaded,+unloading,+unloaded,控制指令 $exist 以及事件處理指令 + click` 的使用:
toggle existThe status of dynamic span: ${ status }Some content
點(diǎn)擊按鈕將切換作用域字段 exist 的值,進(jìn)而觸發(fā)聲明了 $exist 指令的 span 元素加載或移除。
示例鏈接:https://codepen.io/dagger8224/pen/wvmgRyj
指令綜合示例 2
下面的示例代碼演示了控制指令 $each 和 $checked 的使用:
checkbox${ item }
切換復(fù)選框的勾選狀態(tài),作用域變量 checked 字段的內(nèi)容將隨之發(fā)生變化,這是雙向數(shù)據(jù)綁定指令的典型用法。
示例鏈接:https://codepen.io/dagger8224/pen/PoRpROq
各種指令更詳細(xì)的定義和使用方法參見官網(wǎng)文檔 。
模塊
接下來我們一起了解下 dagger.js 的模塊設(shè)計(jì)。
在 dagger.js 中,我們把 html 模板,腳本,層疊樣式表等可復(fù)用的代碼片段統(tǒng)稱為模塊。
dagger.js 內(nèi)部維護(hù)了一個(gè)運(yùn)行時(shí)模塊管理器,開發(fā)者通過 json 格式的配置項(xiàng)注冊模塊,框架將在應(yīng)用程序首次加載或頁面內(nèi)路由發(fā)生切換時(shí)觸發(fā)模塊資源按需動(dòng)態(tài)加載、解析和執(zhí)行。
與作用域數(shù)據(jù)類似,模塊僅在其注冊層級及子層級生效,避免對全局作用域造成污染。
您可以根據(jù)業(yè)務(wù)需求靈活配置模塊的組合方式(每一個(gè)組合方案構(gòu)成一個(gè)名空間)來實(shí)現(xiàn)代碼復(fù)用。我們來看一個(gè)模塊配置項(xiàng)的示例:
上面的配置項(xiàng)中,我們注冊了一個(gè)名為 script 的腳本模塊,一個(gè)名為 style 的樣式模塊,和一個(gè)名為 template 的模板模塊,并將樣式模塊的作用范圍限定為模板模塊內(nèi)部。
示例鏈接:https://codepen.io/dagger8224/pen/rNJrzzj
路由
作為一個(gè)完備的單頁應(yīng)用開發(fā)框架,dagger.js 內(nèi)置了基于瀏覽器 hash 的路由管理器。當(dāng)頁面路由發(fā)生切換時(shí),根作用域下 $router 對象的內(nèi)容將同步變化,進(jìn)而驅(qū)動(dòng)頁面視圖產(chǎn)生響應(yīng)式更新(需要配合 $html 控制指令使用)。我們來看一個(gè)示例:
上例中,當(dāng)路由從 root 切換至 parent1 之后,頁面內(nèi)容將發(fā)生切換。
示例鏈接:https://codepen.io/dagger8224/pen/zYRQrwP
路由對象的字段內(nèi)容可以在下面的示例中查看:
示例鏈接:https://codepen.io/dagger8224/pen/PoQBovd
渲染性能
dagger.js 并未采用虛擬 DOM 方案,而是通過細(xì)粒度的指令執(zhí)行來實(shí)現(xiàn)頁面視圖增量更新。在 js-framework-benchmark 測試場景中,其綜合運(yùn)行時(shí)性能與 React17 版本相當(dāng)。
未來計(jì)劃
dagger.js 目前已經(jīng)在多家公司的 B 端管理系統(tǒng)當(dāng)中得到應(yīng)用。在未來,我們計(jì)劃圍繞框架持續(xù)建設(shè)周邊生態(tài),通過開源方式對框架進(jìn)行推廣運(yùn)營,讓更多的前端開發(fā)者有機(jī)會了解和使用 dagger.js。
總結(jié)
dagger.js 是一個(gè)輕量級無依賴的描述式前端開發(fā)框架,與主流框架相比,具有更低的學(xué)習(xí)和使用成本。用戶僅需了解上文中介紹的指令,模塊與路由的相關(guān)概念和用法,就可以快速上手使用 dagger.js 構(gòu)建單頁應(yīng)用程序。
以上是對 dagger.js 主要功能特性的概要介紹。更多信息請查看官方文檔:https://daggerjs.org
github 地址:https://github.com/dagger8224/dagger.js
更多示例截圖three.js
示例鏈接:https://codepen.io/dagger8224/pen/QWmwaLq
3D Carousel
示例鏈接:https://codepen.io/dagger8224/pen/JjLRbmz
Tesla
示例鏈接:https://codepen.io/dagger8224/pen/RwMGvPv?editors=1010
color picker
示例鏈接:https://codepen.io/dagger8224/pen/vYRmGJp?editors=1010
progress bar
示例鏈接:https://codepen.io/dagger8224/pen/dympJXz?editors=1010
text animation
示例鏈接:https://codepen.io/dagger8224/pen/JjLXppg
您可以在 https://codepen.io/dagger8224/pens 網(wǎng)站查看用 dagger.js 編寫的更多有趣的 demo:
- empty page: https://codepen.io/dagger8224/pen/ZErWBpB
- to do list: https://codepen.io/dagger8224/pen/QWQVYGN
- $scope animation: https://codepen.io/dagger8224/pen/YzeNmRz
- anime.js: https://codepen.io/dagger8224/pen/eYMpzvB
- clock: https://codepen.io/dagger8224/pen/RwMWRYd?editors=1000
- digital clock: https://codepen.io/dagger8224/pen/LYdZEag
- add tags: https://codepen.io/dagger8224/pen/ZErjzwm