- 關於AvalonJs
- 開始的例子
- 掃描
- 視圖模型
- 數據模型
- 綁定屬性與動態模板
- 作用域綁定(ms-controller, ms-important)
- 模板綁定(ms-include)
- 數據填充(ms-text, ms-html)
- 類名切換(ms-class, ms-hover, ms-active)
- 事件綁定(ms-on,……)
- 顯示綁定(ms-visible)
- 插入綁定(ms-if)
- 雙工綁定(ms-duplex,原來的ms-model)
- 樣式綁定(ms-css)
- 數據綁定(ms-data)
- 布爾屬性綁定(ms-checked, ms-selected, ms-readonly, ms-disabled, ms-enabled)
- 字符串屬性綁定(ms-title, ms-src, ms-href……)
- 萬能屬性綁定(ms-attr)
- 萬能綁定(ms-bind)
- 循環綁定(ms-each)
- UI綁定(ms-ui)
- $watch
- 過濾器
- AMD加載器
關於AvalonJS
avalon是一個迷你的MVVM框架,雖然從發佈到現在,它臌脹了不少,但它現在還是比knockout小許多。avalon開發過程一直遵循三個原則:1,複雜即錯誤,2,數據結構優於算法,3,出奇制勝。這三大原則保證avalon具有良好的維護性,擴展性,與衆不同。
簡單說一下其他三大MVVM的實現思路:
- knockout:最早冒出來的JS MVVM庫,通過轉換VM中所有要監聽的東西爲函數,然後執行它們,得到某一時刻中,一共有多少函數被執行,將它們放到棧中,最底的就是最先被執行的,它上面的就是此函數所依賴的函數,從而得到依賴關係。 然後設計一個觀察者模式,從上面的依賴檢測中,將依賴函數作爲被依賴者(最先執行的那個的)的訂閱者,以後我們對被依賴者進行賦值時,就會通先訂閱者更新自身,從而形成一個雙向綁定鏈。 並且,knockout會將視圖中的綁定屬性進行轉換,分解出求值函數與視圖刷新函數,視圖刷新函數依賴於求值函數,而求值函數亦依賴於我們VM中的某些屬性(這時,它們都轉換爲函數),在第一次掃描時,它們會加入對應屬性的訂閱者列隊中,
從而VM中的某個屬性改變,就會自動刷新視圖。
評價:實現非常巧妙,是avalon0.1-0.3的重要學習對象,但將屬性變成一個函數,讓人用點不習慣,許多用法都有點笨笨的。 雖然是一個輕盈的庫,但擴展性不強,裏面的實現異常複雜,導致能參與源碼的人太少。 - emberjs: 一個大而全的框架,包羅萬象。一開始是使用Object.defineProperty+觀察者實現,但IE8的問題,讓它不得不啓用上帝setter, 上帝getter。沒有自動收集依賴的機制,沒有監控數組,計算屬性需要自己指定依賴。VM可繼承。 VM與視圖的雙向綁定依賴於其強大無比上萬行的Handlebars 模板。聽說是外國目前最好用的MV*框架。因爲作者既是jQuery的核心成員,也是Rails的核心成員,雖然由於技術能力沒實現自動收集依賴,但框架的其他方面做得非常易上手,人性化。
評價:太大了,優缺點同python的Django框架。 - angular: google組織開發的框架,體現其算法至上的時候到了。裏面一共有兩個parser, 一個是ngSanitize/sanitize.js下的HTML parser, 一個是ng/parse.js(它要配合compile.js使用)的JS parser。第一個parser負責綁定抽取,第二個負責從Ctrl函數,工廠函數,服務函數及$watch回調中分解出無數setter, getter, 確認它們的依賴關係,放進觀察者模式中。它的觀察者無比強大,由於它的VM能繼承,於是通過繼承鏈實現四通發達的消息廣播。它還實現了一個基於LRU的緩存系統,因爲google最喜歡以空間換時間了,另一方面說明它要緩存的東西太多了,非常吃內存。
公司內部用angular實現的grid,200行在PC中就拖不動了。它還用到許多時髦的東東,如HTML5 history API, 迷你版Q Promise。內部是極其複雜。 不過最大的問題是,它是基於parser,靜態編譯,這意思着什麼呢?不抗壓縮!爲此,它引進了IOC,官網上給出的簡單例子其實在項目完全不可用,我們需要使用另一種更復雜的寫法,方便編澤器從它們得到不被壓縮的部分, 讓它在壓縮情況也能正常運行。由於基於編譯,許多行爲都不是即時的,可預見的。用戶寫的那些控制器函數,都是爲編譯做準備。由於基於編譯,它不得不要求我們對具有兼容問題的一些全局函數,方法進行屏蔽,用它的給出的服務替代它們,如
window對應$window, document對應$document, location對應$location, setTimout對應$timeout……如果不遵循這規則,它可能運行不了,你需要手動使用$digest手動觸發。不過,它與emberjs一樣,走大而全的道路,連測試框架也有了,並且由於是MVVM,因此比起其他框架易寫測試。
評價:上手難度非常大,沒有想象中的好用。有句話是這樣說的,Backbone像是穿救生衣游泳,你要自己游到對岸去,Angular像是開快艇,但是沒有救生衣。
現在的avalon是我在完全消化了knockout發展起來的,準確來說,是0.4版,通過Object.defineProperties與VBScript實現了與普通對象看起來沒什麼兩樣的VM,VM裏面充滿了訪問器屬性,而訪問器屬性肯定對應一個setter,一個getter, 我們就在setter, getter中走knockout的老路,實現自動收集依賴,然後放進一個簡單的觀察者模式中,從而實現雙向綁定。將綁定屬性分解爲求值函數與視圖刷新函數,早前,avalon也與knockout一樣使用一個簡單的parser,然後通過with實現, 0.82一個新的parser 上馬,同樣的迷你,但生成的求值函數,更方便依賴收集,並且沒有with語句,性能更佳。angular也不是一無是處,我也從它那裏抄來了{{}}插值表達式,過濾器機制,控制器綁定什麼的。
avalon在內部使用了許多巧妙的設計,因此能涵蓋angular絕對大多數功能,但體積卻非常少。此外,在性能上,現在除了chrome外,它都比knockout快,angular則是最慢的。 在移動端上,avalon這個優勢會被大大放大化的。
關於avalon的幾點:
- 兼容IE6
- 沒有AJAX與動畫模塊,需要配合jQuery等庫使用
- avalon會自動同步視圖,因此不要在VM中進行DOM操作
迷你MVVM框架在github的倉庫https://github.com/RubyLouvre/avalon, 如果你要兼容IE6,那麼下其中的avalon.js, 如果你只打算兼容IE10與標準瀏覽器,那麼下avalon.mobile.js。
官網地址http://rubylouvre.github.io/mvvm/
大家可以加入QQ羣:79641290進行討論,此羣爲技術羣,禁水!
開始的例子
我們從一個完整的例子開始認識 avalon :
- <!DOCTYPE html>
- <html>
- <head>
- <title></title>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <script src="avalon.js"></script>
- </head>
- <body>
- <div ms-controller="box">
- <div style=" background: #a9ea00;" ms-css-width="w" ms-css-height="h" ms-click="click"></div>
- <p>{{ w }} x {{ h }}</p>
- <p>W: <input type="text" ms-model="w" data-event="change"/></p>
- <p>H: <input type="text" ms-model="h" /></p>
- </div>
- <script>
- avalon.define("box", function(vm) {
- vm.w = 100;
- vm.h = 100;
- vm.click = function() {
- vm.w = parseFloat(vm.w) + 10;
- vm.h = parseFloat(vm.h) + 10;
- }
- })
- </script>
- </body>
- </html>
上面的代碼中,我們可以看到在JS中,沒有任何一行操作DOM的代碼,也沒有選擇器,非常乾淨。在HTML中, 我們發現就是多了一些以ms-開始的綁定屬性與{{}}插值表達式,有的是用於渲染樣式, 有的是用於綁定事件。在ms-model中,我們會發現它會反過來操作VM,VM的改變也會影響視圖的其他部分。
掃描
不過上面的代碼並不完整,它能工作,是因爲框架默認會在DOMReady時掃描DOM樹,將視圖中的綁定屬性與{{}}插值表達式抽取出來,轉換爲求值函數與視圖刷新函數。
我們可以通過下面方法自己掃描DOM樹:
- avalon.ready(function() {
- avalon.define("box", function(vm) {
- vm.w = 100;
- vm.h = 100;
- vm.click = function() {
- vm.w = parseInt(vm.w) + 10;
- vm.h = parseInt(vm.h) + 10;
- }
- })
- avalon.scan()
- })
scan有兩個可選參數,第一個是掃描的起點元素,默認是HTML標籤,第2個是VM對象。
- //源碼
- avalon.scan = function(elem, vmodel) {
- elem = elem || root
- var vmodels = vmodel ? [].concat(vmodel) : []
- scanTag(elem, vmodels)
- }
視圖模型
我們是通過avalon.define函數返回一個視圖對象VM,並且avalon.define(vmName, function(vm){})中的vm並不等於VM,工廠函數中的vm是用於轉換爲VM的。生成的VM比用戶指定的屬性還多了許多屬性。
默認的,除了函數外,其他東西都轉換爲監控屬性,計算屬性與監控數組。如果不想讓它轉換,可以讓此屬性以 $開頭,框架就不會轉換它們。
如果實在不放便改名,又不想被轉換,比如是一個jQuery對象或一個DOM節點,如果轉換,肯定拖死框架,我們可以放到vm.$skipArray = [propName1, propName2]中去,這樣也忽略轉換。
另外,avalon不允許在VM定義之後,再追加新屬性與方法,比如下面的方式是錯誤的:
var vm = avalon.define("test", function(vm) { vm.test1 = '點擊測試按鈕沒反應 綁定失敗'; }); vm.one = function() { vm.test1 = '綁定成功'; }; //這裏有兩個錯誤, //1在命名上沒有區分avalon.define的返回值與它回調中的參數, //2one方法的定義位置不對(這是考慮到兼容IE6-8,要求所有瀏覽器保持行爲一致)
數據模型
當我們要用AJAX與後端交互時,如果直接把VM傳上去太大了,這時我們需要把它對應的純數組的JS對象。在VM中有個叫$model的屬性,這是一個對象,就是數據模型M了。當我們更改VM時,框架就會自動同步M
綁定屬性與動態模板
在開始之前,我們看一下靜態模板是怎麼工作的:
我之前寫了一個叫ejs的靜態模板引擎:
- <script type="tmpl" id="table_tmpl">
- <&= title() &>
- <table border=1>
- <&- for(var i=0,tl = @trs.length,tr;i<tl;i++){ -&>
- <&- tr = @trs[i]; -&>
- <tr>
- <td><&= tr.name;; &></td> <td><&= tr.age; &></td> <td><&= tr.sex || "男" &></td>
- </tr>
- <& } &>
- </table>
- <&# 怎麼可能不支持圖片 &>
- <img src="<&= @href &>">
- </script>
它是以一個script標籤做容器,裏面的整個叫模板。模板裏面有許多以 <& 與 &>劃分出來的區塊,用於插入JS代碼,以@開頭的變量是對應於數據包中的某個屬性。
幾乎所有靜態模板的實現原理都是一樣的,將這個模板變成一個函數,然後裏面分成靜態部分與動態部分,靜態部分就是上面的HTML部分,轉換爲一個個字符串,動態部分就是插入的JS代碼, 它們基本上原封不動地成爲函數體的邏輯。然後我們傳入一個對象給這個函數,最後得到一個符合HTML格式的字符串,最後用它貼到頁面上某個位置就行了。
靜態模板有幾個缺點,首先它容易混入大量的JS邏輯,對於菜鳥來說,他們特別喜歡在裏面放入越來越多JS代碼。這個在JSP年代,已經證明是bad practice。爲此出現了logic-less的 mustache。 其次,它更新視圖總是一大片一大片地處理,改動太大。最後,是由於第2點引發的問題,它對事件綁定等不友好,因爲一更新,原來的節點都被消滅了,需要重新綁定。幸好,jQuery普及了事件代理,這問題纔沒有 暴露出來。
再看動態模板,幾乎所有MVVM框架都用動態模板(當然也有例外,如emberjs)。動態模板以整個DOM樹爲容器,它通過掃描方式進行第一次更新視圖。 在靜態模板,通過<& 與 &>劃分的部分,轉換爲綁定屬性與{{}}插值表達式(這是一種文本綁定,在avalon中,我們可以通過|html過濾器,轉換html綁定) 這樣就有效阻止用戶在頁面上寫邏輯。雖然動態模板也支持ms-if, ms-each等表示邏輯關係的綁定,但它的值最複雜也只能是一個表達式。 在綁定屬性中,屬性名用於指定操作行爲,如切換類名,控制顯示,循環渲染,綁定事件,數據填充什麼的,而屬性值是決定這些操作是否執行,與渲染結果。 由於雙向綁定的關係,它不像靜態模板那樣,每次都要自己將數據包放進函數,得到結果,然後innerHTML刷新某個區域。它是在用戶爲VM的某個屬性進行重新賦值,將視圖中對應的某個文本節點, 特性節點或元素節點的值進行重刷。因此不會影響事件綁定。
在avalon中,這些視圖刷新函數都有個element屬性,保持對應的元素節點,每次同步時,都會檢測此元素節點是否在DOM樹,不在DOM樹就取消訂閱此刷新函數,節約內存,防止無效操作。
因此,你們可以看區別了吧。綁定屬性與插值表達式就是對應靜態模板中的JS邏輯部分,由於只允許爲表達式或單個屬性值,複雜度被控制了,強制用戶將它們轉移到VM中。 VM作爲一個數據源,對應靜態模板的數據包,並且多了一個自動觸發功能,進化成一個消息中心。
- <p ms-controller="test" ms-click="click">{{ a }}</p>
- <script>
- avalon.define("test", function(vm) {
- vm.a = '123';
- vm.click = function() {
- vm.a = new Date - 0
- }
- })
- </script>
最後要注意的是,HTML5已經規定,特性節點的名字只能小寫,因此什麼ms-ui-xxx, 都要小寫化!這是瀏覽器行爲,無可奈何。
作用域綁定(ms-controller, ms-important)
avalon提供ms-controller, ms-important來指定VM在視圖的作用範圍。比如有兩個VM,它們都有一個firstName屬性,在DIV中,如果我們用 ms-controller="VM1", 那麼對於DIV裏面的{{firstName}}就會解析成VM1的firstName中的值。
有關它們的詳細用法,可見這裏。
模板綁定(ms-include)
如果單是把DOM樹作爲一個模板遠遠不夠的,比如有幾個地方,需要重複利用一套HTML結構,這就要用到內部模板或外部模板了。
內部模板是,這個模板與目標節點是位於同一個DOM樹中。我們用一個MIME不明的script保存它,然後通過ms-include="id"引用它。
- <script type="text/avalon" id="tpl">
- here, {{ 1 + 1 }}
- </script>
- <div ms-include="'tpl'"></div>
注意,ms-include的值要用引號括起,表示這只是一個字符串,這時它就會搜索頁面的具有此ID的節點,取其innerHTML,放進ms-include所在的元素內部。否則這個tpl會被當成一個變量, 框架就會在VM中檢測有沒有此屬性,有就取其值,重複上面的步驟。如果成功,頁面會出現here, 2的字樣。
外部模板,通常用於多個頁面的複用,因此需要整成一個獨立的文件。這時我們就需要通過ms-include-src="src"進行加載。
比如有一個HTML文件tmpl.html,它的內容爲:
- <div>這是一個獨立的頁面</div>
- <div>它是通過AJAX的GET請求加載下來的</div>
然後我們這樣引入它
- <div ms-include-src="'tmpl.html'"></div>
數據填充(ms-text, ms-html)
這分兩種:文本綁定與HTML綁定,每種都有兩個實現方式
- <script>
- avalon.define("test", function(vm) {
- vm.text = "<b> 1111 </b>"
- })
- </script>
- <div ms-controller="test">
- <div><em>用於測試是否被測除</em>xxxx{{text}}yyyy</div>
- <div><em>用於測試是否被測除</em>xxxx{{text|html}}yyyy</div>
- <div ms-text="text"><em>用於測試是否被測除</em>xxxx yyyy</div>
- <div ms-html="text"><em>用於測試是否被測除</em>xxxx yyyy</div>
- </div>
類名切換(ms-class, ms-hover, ms-active)
avalon提供了多種方式來綁定類名,有ms-class, ms-hover, ms-active, 具體可看這裏
事件綁定(ms-on)
avalon通過ms-on-click或ms-click進行事件綁定,並在IE對事件對象進行修復,並統一了所有瀏覽器對return false的處理。具體可看這裏
avalon並沒有像jQuery設計一個近九百行的事件系統,連事件回調的執行順序都進行修復(IE6-8,attachEvent添加的回調在執行時並沒有按先入先出的順序執行),只是很薄的一層封裝,因此性能很高。
- ms-click
- ms-dblclick
- ms-mouseout
- ms-mouseover
- ms-mousemove
- ms-mouseenter
- ms-mouseleave
- ms-mouseup
- ms-mousedown
- ms-keypress
- ms-keyup
- ms-keydown
- ms-focus
- ms-blur
- ms-change
- ms-on-*
顯示綁定(ms-visible)
avalon通過ms-visible="bool"實現對某個元素顯示隱藏控制,對於低版本的瀏覽器,它用的是style.display="none"進行隱藏,對於支持HTML5的瀏覽器,它是使用hidden屬性來控制。因此它是優於其他MVVM的實現。
插入綁定(ms-if)
這個功能是抄自knockout的,ms-if="bool",同樣隱藏,但它是將元素移出DOM。這個功能直接影響到CSS :empty僞類的渲染結果,因此比較有用。
雙工綁定(ms-duplex)
這功能抄自angular,原名ms-model起不得太好,姑且認爲利用VM中的某些屬性對錶單元素進行雙向綁定。打算啓用一個新名字叫ms-duplex
這個綁定,它除了負責將VM中對應的值放到表單元素的value中,還對元素偷偷綁定一些事件,用於監聽用戶的輸入從而自動刷新VM。具體如下:
- text, password, textarea
- 默認是通過input事件進行監聽,舊式IE是通過propertychange實現,換言之,每改一個字符串都觸發。如果想在失去焦點時才觸發,可以在元素上使用data-event="change"進行調整。 它要求VM對應的屬性爲一個字符串或數字,不過觸發一次之後,屬性就會變成字符串。
- radio
- 默認是通過change事件進行監聽,舊式IE是通過chick實現, 它要求VM對應的屬性爲一個布爾。
- checkbox
- 默認是通過change事件進行監聽, 它要求VM對應的屬性爲一個字符串數組。
- select
- 默認是通過change事件進行監聽, 它要求VM對應的屬性爲一個字符串或字符串數組(視multiple的值)。
樣式綁定(ms-css)
用法爲ms-css-name="value"
- <div ms-css-width="aaa"></div>
數據綁定(ms-data)
用法爲ms-data-name="value", 用於爲元素節點綁定HTML5 data-*屬性。
布爾屬性綁定
這主要涉及到表單元素幾個非常重要的布爾屬性,即disabed, readyOnly, selected , checked, 分別使用ms-disabled, ms-enabled, ms-readonly, ms-checked, ms-selected。ms-disabled與ms-enabled是對立的,一個true爲添加屬性,另一個true爲移除屬性。
字符串屬性綁定
這主要涉及到幾個非常常用的字符串屬性,即href, src, alt, title, value, 分別使用ms-href, ms-src, ms-alt, ms-title, ms-value。它們的值的解析情況與其他綁定不一樣,如果值沒有{{}}插值表達式,那麼就當成VM中的一個屬性,並且可以與加號,減號混用, 組成表達式,如果裏面有表達式,整個當成一個字符串。
- <a ms-href="aaa + '.html'">xxxx</a>
- <a ms-href="{{aaa}}.html">xxxx</a>
萬能屬性綁定(ms-attr)
ms-attr-name="value",這個允許我們在元素上綁定更多種類的屬性,如className, tabIndex, name, colSpan什麼的。
萬能綁定(ms-bind)
ms-bind是一種非常強大的同步機制,因爲它允許你持續監聽某一個VM屬性的變化,並且它的參數是一個函數,this又是指向綁定屬性的元素節點,因此比ms-css, ms-attr, ms-data, ms-click等有着因定DOM操作的綁定來得更靈活。
用法: ms-bind-prop="callback", 其中prop, callback都要求來自同一個VM。callback爲一個函數,this指向元素節點。
- <div ms-controller="test">
- <div ms-bind-aaa="callback"></div>
- <button ms-click="one">點我</button>
- </div>
- avalon.define("test", function(vm) {
- vm.aaa = 1111;
- vm.callback = function() {
- this.innerHTML = vm.aaa
- }
- vm.one = function() {
- vm.aaa = new Date - 0
- }
- });
循環綁定(ms-each)
用法爲ms-each-xxx="array", 其中xxx可以隨意改,如yyy, el, 它是用於在子元素中進行引用。array對應VM中的一個普通數組或一個監控數組。詳見這裏。
- <script>
- avalon.define("test", function(vm) {
- vm.array = [{value: "aaa", text: "111"}, {value: "bbb", text: "222"}, {value: "bbb", text: "333"}]
- })
- </script>
- <div ms-controller="test">
- <select ms-each-el="array">
- <option ms-value="el.value">{{$index}}、{{el}}</option>
- </select>
- </div>
UI綁定(ms-ui)
它的格式爲ms-ui-$opts="uiName", 其他$opts可有可無,存在時對應VM中的一個對象,建議將它設置爲不可監控的,因爲它只是作爲一個配置對象。uiName爲控件的名字。
此外,在綁定元素上還應該設置一個data-id屬性,用於指定生成的UI控件對應的VM的名字。你也可以設置更多的data-*屬性,方便用於配置UI。
下面是一個完整的實例用於教導你如何定義使用一個UI。
$watch
這是一個位於VM的方法,用於監聽VM的某人屬性的變化,回調中有兩個傳參,新屬性值與舊屬性值,裏面的this指向VM,詳見這裏。
過濾器
avalon從angular中抄來管道符風格的過濾器,但有點不一樣。 它只能用於{{}}插值表達式。如果不存在參數,要求直接跟|filter,如果存在參傳,則要用小括號括起,參數要有逗號,這與一般的函數調用差不多,如|truncate(20,"……")
avalon自帶以下幾個過濾器
- html
- 沒有傳參,用於將文本綁定轉換爲HTML綁定
- uppercase
- 大寫化
- lowercase
- 小寫化
- truncate
- 對長字符串進行截短,truncate(number, truncation), number默認爲30,truncation爲“...”
- camelize
- 駝峯化處理
- escape
- 對類似於HTML格式的字符串進行轉義,把尖括號轉換爲> <
- currency
- 對數字添加貨幣符號,以及千位符, currency(symbol)
- number
- 對數字進行各種格式化,這與與PHP的number_format完全兼容, number(decimals, dec_point, thousands_sep),
decimals 可選,規定多少個小數位。 dec_point 可選,規定用作小數點的字符串(默認爲 . )。 thousands_sep 可選,規定用作千位分隔符的字符串(默認爲 , ),如果設置了該參數,那麼所有其他參數都是必需的。
- date
- 對日期進行格式化,date(formats)
- 'yyyy': 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)
- 'yy': 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)
- 'y': 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)
- 'MMMM': Month in year (January-December)
- 'MMM': Month in year (Jan-Dec)
- 'MM': Month in year, padded (01-12)
- 'M': Month in year (1-12)
- 'dd': Day in month, padded (01-31)
- 'd': Day in month (1-31)
- 'EEEE': Day in Week,(Sunday-Saturday)
- 'EEE': Day in Week, (Sun-Sat)
- 'HH': Hour in day, padded (00-23)
- 'H': Hour in day (0-23)
- 'hh': Hour in am/pm, padded (01-12)
- 'h': Hour in am/pm, (1-12)
- 'mm': Minute in hour, padded (00-59)
- 'm': Minute in hour (0-59)
- 'ss': Second in minute, padded (00-59)
- 's': Second in minute (0-59)
- 'a': am/pm marker
- 'Z': 4 digit (+sign) representation of the timezone offset (-1200-+1200)
- format string can also be one of the following predefined localizable formats:
- 'medium': equivalent to 'MMM d, y h:mm:ss a' for en_US locale (e.g. Sep 3, 2010 12:05:08 pm)
- 'short': equivalent to 'M/d/yy h:mm a' for en_US locale (e.g. 9/3/10 12:05 pm)
- 'fullDate': equivalent to 'EEEE, MMMM d,y' for en_US locale (e.g. Friday, September 3, 2010)
- 'longDate': equivalent to 'MMMM d, y' for en_US locale (e.g. September 3, 2010
- 'mediumDate': equivalent to 'MMM d, y' for en_US locale (e.g. Sep 3, 2010)
- 'shortDate': equivalent to 'M/d/yy' for en_US locale (e.g. 9/3/10)
- 'mediumTime': equivalent to 'h:mm:ss a' for en_US locale (e.g. 12:05:08 pm)
- 'shortTime': equivalent to 'h:mm a' for en_US locale (e.g. 12:05 pm)
例子:
生成於{{ new Date | date("yyyy MM dd:HH:mm:ss")}}
生成於{{ "2011/07/08" | date("yyyy MM dd:HH:mm:ss")}}
生成於{{ "2011-07-08" | date("yyyy MM dd:HH:mm:ss")}}
生成於{{ "01-01-2000" | date("yyyy MM dd:HH:mm:ss")}}
生成於{{ "03 04,2000" | date("yyyy MM dd:HH:mm:ss")}}
生成於{{ "3 4,2000" | date("yyyy MM dd:HH:mm:ss")}}
生成於{{ 1373021259229 | date("yyyy MM dd:HH:mm:ss")}}
生成於{{ "1373021259229" | date("yyyy MM dd:HH:mm:ss")}}
值得注意的是,new Date可傳的格式類型非常多,但不是所有瀏覽器都支持這麼多,詳看這裏
多個過濾器一起工作
- <div>{{ prop | filter1 | filter2 | filter3(args, args2) | filter4(args)}}</div>
如果想自定義過濾器,可以這樣做
- avalon.filters.myfilter = function(str, args, args2){//str爲管道符之前計算得到的結果,默認框架會幫你傳入,此方法必須返回一個值
- /* 具體邏輯 */
- return ret;
- }
AMD 加載器
avalon裝備了AMD模範的加載咕咕,這涉及到兩個全局方法 require與define
require(deps, callback)
deps 必需。String|Array。依賴列表,可以是具體路徑或模塊標識,如果想用字符串表示多個模塊,則請用“,”隔開它們。
callback 必需。Function。回調,當用戶指定的依賴以及這些依賴的依賴樹都加載執行完畢後,纔會安全執行它。
如果想禁止使用avalon自帶的加載器,可以在第一次調用require方法之前,執行如下代碼:
- avalon.config({loader: false})
define方法用於定義一個模塊,格式爲:
define( id?, deps?, factory )
id 可選。String。模塊ID。它最終會轉換一個URL,放於 $.modules中。 deps 可選。String|Array。依賴列表。 factory 必需。Function|Object。模塊工廠。它的參數列參爲其依賴模塊所有返回的值,如果某個模塊沒有返回值,則對應位置爲undefine