介紹 Elf.js 是一個簡潔的高效的 框架。它不僅高度重視用戶的體驗,也高度重視開發者的體驗。在實現當今主流技術的同時,以儘可能原生態的形式展現出來。在如今花樣繁多的框架中,你是否感覺各種思想、語法、工具大大增加了你的學習時間,那麼 是一個不錯的開始。她將最初的 Web 設計理念與現代技術完美結合 ...
介紹
Elf.js 是一個簡潔的高效的
JavaScript
框架。它不僅高度重視用戶的體驗,也高度重視開發者的體驗。在實現當今主流技術的同時,以儘可能原生態的形式展現出來。在如今花樣繁多的框架中,你是否感覺各種思想、語法、工具大大增加了你的學習時間,那麼Elf.js
是一個不錯的開始。她將最初的 Web 設計理念與現代技術完美結合,她追求的是簡單、明朗、返璞歸真。
安裝
NPM
npm install elfjs --save
- 文件
- 在
NPM
包的目錄你將找到.js(完整版)
、.min.js(迷你版)
以及.d.ts(類型聲明)
文件。 elf-loader.js
提供簡單的AMD/CommonJS
規範的載入器,她可以讓你在開發中免去編譯的等待。shims
目錄下的提供在IE9
上運行的補丁與集成第三方庫的補丁。她們並不是時常用到。- 使用支持 DefinitelyTyped 的 IDE 可以有效的進行代碼提示與類型檢查。
- 在
開始
Elf.js
並未創建過多的私有思想和語法。若你已經具有 Web 中級知識,那麼一切將非常得心應手。
第一個組件
Elf.js
採用簡潔的模板語法來聲明 DOM 與數據。<!-- viewComponent.html --> <div> {{ message }} </div>
// viewComponent.js var temp = require("viewComponent.html"); module.exports = Elf.Component("view", { constructor : function () { this.message = "Hello Word!"; }, render : Elf.redactElement(temp) });
// bootstrap.js var View = require("viewComponent"); Elf.render(Elf.createElement(View), document.body, true);
- 上面的代碼展示瞭如何從模板中創建組件和如何將組件渲染到指定節點。
更多模板語法參見 模板語法
使用指令
Elf.js
提供可增強HTML
特性的功能。下麵將展示一個簡單的拖動功能。// dragDirective.js module.exports = Elf.Directive("drag", { onInitial : function (element, props) { Elf.attachEvent(element, "mousedown", this); Elf.attachEvent(element, "mousemove", this); Elf.attachEvent(element, "mouseup", this); }, onDispose : function (element, props) { Elf.detachEvent(element, "mousedown", this); Elf.detachEvent(element, "mousemove", this); Elf.detachEvent(element, "mouseup", this); }, handleEvent : function (event) { // coding drag } });
<!-- viewComponent.html --> <div cmd="drag"> {{ message }} </div>
// viewComponent.js var temp = require("viewComponent.html"); var dragDirective = require("dragDirective"); module.exports = Elf.Component("view", { constructor : function () { this.message = "Hello Word!"; }, render : Elf.redactElement(temp, dragDirective) });
- 通過
Elf.Directive
方法,我們定義並實現了一個拖動指令。通過Elf.redactElement
函數註入依賴的指令(已經通過Elf.depend
方法註冊為全局依賴則不必在這裡註入了),就可以在模板中通過指令別名使用了。此時的div
已經具備拖動能力。 指令能有效的將功能操作與業務邏輯分離,並高度重用代碼。
使用管道
在渲染過程中,往往數據需要轉換成某種特定格式,我們可以通過
Transform
來實現。例如下麵代碼將日期格式化輸出。// dateTransform.js module.exports = Elf.Transform("date", { transform : function (value, formatExpr) { return moment(value).format(formatExpr); } });
<!-- viewComponent.html --> <div cmd="drag"> {{ now | date "YYYY-MM-DD" }} </div>
// viewComponent.js var temp = require("viewComponent.html"); var dateTransform = require("dateTransform"); module.exports = Elf.Component("view", { constructor : function () { this.now = new Date(); }, render : Elf.redactElement(temp, dateTransform) });
- 上面的代碼最終將日期輸出為
xxxx-xx-xx
格式。 管道與指令一樣,都是為了將功能操作與業務邏輯分離,使得相同的功能能得以重用。
事件處理
Elf.js
的事件綁定與原生HTML
一樣。<!-- viewComponent.html --> <button onclick="onClick($event);"> 點擊試試 </button>
// viewComponent.js var temp = require("viewComponent.html"); module.exports = Elf.Component("view", { render : Elf.redactElement(temp), onClick : function (event) { alert("點擊被觸發了!"); } });
Elf.js
將會自動管理事件的綁定與移除,即使在迴圈中也不必擔心作用域的問題。也不必擔心性能問題。Elf.js
提供了一套與原生一樣的冒泡機制,Component
亦可作為觸發事件的對象。
組件通訊
- 因為
Elf.js
實現的事件機制與原生相同,並且可作用與Component
,所以Elf.js
不需要額外的狀態管理手段。子組件的事件通過這種機制會冒泡到Individual
,你只需在Individual
處處理業務邏輯即可。又因為Elf.js
是自動響應的,你也不需要關心數據變化後的呈現。她會自動分析新的數據與之前的數據,將更新呈現在頁面上。 Elf.js
並不提供雙向綁定
,亦不推崇單向數據流
。原始的事件機制就是最好的手段,她早已深入每一個前端程式員心中。- 這裡我們使用一個完整的示例 elfjs-calendar 。
- 在
sldier.js
與calendar.js
里分別拋出了日曆操作事件,在main.js
業務邏輯。
進階
正如上面的教程,
Elf.js
核心只提供了Component
、Directive
和Transform
三個對象。模板中只提供了兩個控制流程的屬性(e-for
和e-if
)和一個文本輸出{{ }}
。但Elf.js
在背後所做的遠遠不止於此。她有著高效的虛擬DOM
和原生一樣的事件機制
,還能自動響應數據變化。如果你想深入瞭解其原理(其實現在主流框架的原理都是相近的)。Elf.js
為一個極簡的框架,將會是一個最好最優的選擇。
深入響應式原理
受 zone.js 啟發。數據的改變的時機無外乎用戶操作(觸發事件)和非同步函數(Ajax
和setTimeout
等)。Elf.js
封裝了事件監聽和常用的非同步操作。使之能夠得到監控,在這些非同步操作結束後,Elf.js
將會去計算數據變化,然後以最優的方式更新DOM
。
集成第三方類庫
由於Elf.js
封裝了原生的事件,但並沒有像 zone.js 一樣侵入。所以通過Elf.js
創建的DOM
不再觸發用原生方法綁定的事件。因此第三方類庫的監聽可能無法觸發其綁定的事件。通過引入shims_for_Lib.js
可以讓Elf.js
接管Window
和Node
的事件監聽。從而讓第三方類庫完美運行,亦可自動響應數據變化。
使用擴展語言
Elf.js
無縫支持JSX
(elf.d.ts
中可以找到JSX
定義)。但Elf.js
更推薦使用模板。相較於JSX
,模板有著良好的結構,視圖與邏輯分離,更好的與UI合作。同時,使用elf-loader.js
載入模板,會有source map
,彌補了模板調試難的短板。
生產環境部署
如同之前的開發一樣,我們使用node
開發,AMD
和CommonJS
的風格都能支持,在開發階段無需編譯、打包,並有source map
輸出,擁有非常好的開發體驗。在使用打包工具(如:webpack)打包後不再輸出source map
,在沒有察覺的情況下就已經提升了性能。打包過程中亦無需其它loader
。當然,若想追求極致性能可以使用loader
將模板預編譯為 JavaScript 。