本版本是一次重要的升級,考慮要介紹許多東西,也有許多東西對你們有用,也發到首頁上來了。javascript
原本是沒有1.36的,先把基於靜態收集依賴的1.4設計出來後,發現改動太多,爲了平緩升級起見,才減小了一部分新特性,作成1.36。所以是先有1.4,纔有1.36。php
本版本針對公司(去哪兒網,畢竟是帶薪在公司裏搞這框架)的訪問瀏覽器的佔有率,加大對國產瀏覽器的測試。涉及瀏覽器有QQ瀏覽器, 搜狗瀏覽器, 獵豹瀏覽器, 傲遊瀏覽器,但沒有360瀏覽器,咱們公司的同事仍是很注意安全的。這麼多瀏覽器,如今還差兩個case才能在獵豹瀏覽器上經過。緣由是獵豹瀏覽器是雙核的,框架一些內部斷定分支不當心掉進坑裏了。如往常同樣,對於正常的IE6-8,avalon是所有經過。 css
下面簡單羅列一下新特性與修復狀況:html
下面是介紹一些具體特徵的實現。前端
首先是isFunction方法,avalon遇到的問題與當年的jQuery是同樣的。jQuery 1.4 源碼 449 行(core.js 431 行),判斷是否爲函數的方法以下(思路來源於 Douglas Crockford 的《The Miller Device》): java
isFunction: function( obj ) { return toString.call(obj) === "[object Function]"; },
同時 jQuery 的做者也做了部分註釋:node
See test/unit/core.js for details concerning isFunction. Since version 1.3, DOM methods and functions like alert aren't supported. They return false on IE (#2968).
即:此方法在 IE 下沒法正確識別 DOM 方法和一些函數(例如 alert 方法等)。若是咱們用alert(typeof document.getElementById),在IE6-8下會彈出object,而不是期待中的function。所以咱們必須對IE6-8或舊式IE內核瀏覽器進行特殊處理,參考了網上的實現,avalon如今的源碼以下: git
var isFunction = typeof alert === "object" ? function(fn) { try {//正則判斷傳入的對象字符串後(fn+""),是否起始位置含有 function,即:/^\s*\bfunction\b/.test(fn+"") return /^\s*\bfunction\b/.test(fn + "") } catch (e) { return false } } : function(fn) { return serialize.call(fn) == "[object Function]" }
但這個方法目前還有一點問題,在獵豹瀏覽器下斷定eval方法會出錯,大抵是在IE8文檔模式下IE9用戶代理字符串模式下出錯。github
ms-duplex-*添加數據轉換功能,如今ms-duplex-bool調整爲ms-duplex-boolean, ms-duplex-text調整爲ms-duplex-string,增長ms-duplex-number,而且它們三個在全部表單元素都上都有效果。預計在1.4中,會添加更多自定義格式與錯誤提示功能。web
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <title>ms-duplex</title> <script src="../avalon.js" type="text/javascript"></script> <script> var model = avalon.define({ $id: "test", aaa: "111", bbb: false, ccc: [222], ddd: [true], eee: [], fff: 222 }) model.$watch("aaa", function(a) { console.log(a) }) model.ccc.$watch("length", function(a) { console.log(model.ccc) }) model.ddd.$watch("length", function(a) { console.log(model.ddd) }) model.eee.$watch("length", function(a) { console.log(model.eee) }) model.$watch("fff", function(a) { console.log(a) }) </script> </head> <body ms-controller="test"> <fieldset><legend>radio</legend> <p><input ms-duplex="aaa" type="radio">根據當前checked屬性取反設置其checked,只應用於單個控件</p> <p><input ms-duplex-string="aaa" value="111" type="radio"> <input ms-duplex-string="aaa" value="222"type="radio"> 根據其value屬性設置其checked</p> <p><input ms-duplex-number="aaa" value="111" type="radio"> <input ms-duplex-number="aaa" value="222"type="radio"> 根據其value屬性設置其checked,要求應用於複數個控件,類型轉換爲number</p> <p><input ms-duplex-boolean="bbb" value="true" type="radio"> <input ms-duplex-boolean="bbb" value="false"type="radio"> 根據其value屬性設置其checked,要求應用於複數個控件,類型轉換爲boolean,原來的ms-duplex-bool</p> <p><input ms-duplex-string="bbb" value="true" type="radio"> <input ms-duplex-string="bbb" value="false"type="radio"> 根據其value屬性設置其checked,要求應用於複數個控件,類型轉換爲string,原來的ms-duplex-text</p> </fieldset> <fieldset><legend>checkbox</legend> <p><input ms-duplex-radio="bbb" type="checkbox">根據當前checked屬性取反設置其checked,只應用於單個控件</p> <p><input ms-duplex-number="ccc" value="111" type="checkbox"> <input ms-duplex-number="ccc" value="222"type="checkbox"> 根據其value屬性設置其checked,要求應用於複數個控件,類型轉換爲number</p> <p><input ms-duplex-boolean="ddd" value="true" type="checkbox"> <input ms-duplex-boolean="ddd" value="false"type="checkbox"> 根據其value屬性設置其checked,要求應用於複數個控件,類型轉換爲boolean</p> <p><input ms-duplex-string="eee" value="男" type="checkbox"> <input ms-duplex-string="eee" value="女"type="checkbox"> 根據其value屬性設置其checked,要求應用於複數個控件,類型轉換爲string</p> </fieldset> <fieldset><legend>text,texteara, password</legend> <p><input ms-duplex-number="aaa">{{typeof aaa}}</p> <p><input ms-duplex-boolean="bbb">{{typeof bbb}}</p> </fieldset> <fieldset><legend>select</legend> <select ms-duplex-number="fff"> <option>111</option> <option>222</option> <option>333</option> </select> </fieldset> </body> </html>
最後是舊式IE設置透明度的問題,你們都知道要使用透明濾鏡。但透明濾鏡其實有兩個版本,一個是簡化版,style.filter="alpha(opacity=50)",一個是完整版, style.filter="progid:DXImageTransform.Microsoft.Alpha(opacity=50)"。jQuery是使用前者,但問題來了,透明濾鏡還有一個設置項,enabled,若是它等於0或false,那麼就不會透明。爲了預防這樣的高手出現,取透明度時就要當心了。
var salpha = "DXImageTransform.Microsoft.Alpha" cssHooks["opacity:get"] = function(node) { //這是最快的獲取IE透明值的方式,不須要動用正則了! var alpha = node.filters.alpha || node.filters[salpha], op = alpha && alpha.enabled ? alpha.opacity : 100 return (op / 100) + "" //確保返回的是字符串 }
在設置透明度時,最開始不存在濾鏡,咱們就必須操做node.style.filter屬性,之後有了,就可使用node.filters對象進行操做。jQuery只打算操做在style上玩。參考mootools的實現,我搞鼓出第一種操做透明度的方式。
cssHooks["opacity:set"] = function(node, name, value) { var style = node.style var opacity = isFinite(value) && value <= 1 ? "alpha(opacity=" + value * 100 + ")" : "" var filter = style.filter || ""; style.zoom = 1 //不能使用如下方式設置透明度 //node.filters.alpha.opacity = value * 100 style.filter = (ralpha.test(filter) ? filter.replace(ralpha, opacity) : filter + " " + opacity).trim() if (!style.filter) { style.removeAttribute("filter") } }
顯然這是沒有有效利用透明濾鏡的特性。深刻研究後,搞出第二種,它將在1.4上出現。
//https://github.com/RubyLouvre/avalon/issues/517 cssHooks["opacity:set"] = function(node, name, value) { var style = node.style var filter = style.filter || "" if (filter.indexOf(salpha) === -1) { style.filter += "progid:" + salpha + "(opacity=100)" } var alpha = node.filters[salpha] || {} if (value <= 1 && isFinite(value)) { style.zoom = alpha.enabled = 1 alpha.opacity = value * 100 } else { alpha.enabled = 0 } }
這樣更簡單,更高效。總之,在DOM上是存在各類奇奇怪怪的屬性與方法,與它們打交道,正是咱們前端寫碼的樂趣所在。掌握的細節越多,咱們的選擇就越多,寫出的代碼就越優雅高效。
迷你MVVM框架在github的倉庫https://github.com/RubyLouvre/avalon
官網地址http://rubylouvre.github.io/mvvm/
avalon的新UI庫地址OniUI, 多達36個UI,強大的換膚功能
朋友們用avalon作的東西