avalon“操作數據即操作DOM”的能力,讓我們可以專致於業務,寫出更專業,更優雅,更易維護的代碼來。現在讓我們看看如何實現一個序列號輸入功能。它的需求以下:
- 每輸入4個字符就跳到下一個輸入框。
- 不能輸入超過4個字符。
- 支持復制貼粘功能,每4個字符自動對位到相應的輸入框。
先給出代碼:
<!DOCTYPE html> <html> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script src="avalon.js"></script> <style> input:focus{ border: 1px solid #a9ea00; background:#f0f0f0; } </style> <script> var model = avalon.define("xxx", function(vm) { vm.seriesNumber = [{value: ""}, {value: ""}, {value: ""}, {value: ""}] vm.focusIndex = NaN //獲得焦點,實現輸入框中的跳轉操作 vm.focus = function(a, b) { var el = this; if (a === avalon(el).data("index")) { setTimeout(function() { el.focus() el.select(); }, 0); } } vm._focus = function() { model.$unwatch() model.focusIndex = avalon(this).data("index") model.$watch() } //通過貼粘實現智能輸入 vm.paste = function(e) { var index = avalon(this).data("index") var text = "" if (e.clipboardData) { avalon.log("w3c") text = e.clipboardData.getData("text/plain"); } else if (window.clipboardData) { avalon.log("ie") text = clipboardData.getData("Text") } var array = text.match(/\w{4}/g) || [] for (var i = 0; i < array.length; i++) { var el = model.seriesNumber[index + i] if (el) { el.value = array[i] } } var last = Math.min(index + i, 3) setTimeout(function() { model.focusIndex = last }, 0) } }) //綁定$watch,實現輸入字數限制與智能跳轉 model.seriesNumber.forEach(function(el, index) { el.$watch("value", function(a, b) { if (a.length >= 4) { model.focusIndex = index + 1 //跳轉 el.value = a.slice(0, 4) } }) }) //剛開始時聚焦到第一個輸入框中 avalon.ready(function() { model.focusIndex = 0 }) </script> </head> <body> <div ms-controller="xxx" ms-each-el="seriesNumber"> <input ms-duplex="el.value" ms-on-paste="paste" ms-focus="_focus" ms-bind="focusIndex: focus" ms-data-index="$index"> </div> <h2>1234aaaabbbb6789</h2> </body> </html>
首先,我們要監聽一個input里面的內容變化,馬上能想到用ms-duplex,該綁定能逐字符地監聽變化。但由於存在多個INPUT,為了方便循環處理,我們用到一個數組。但數組VM中只能監聽它的長度變化。因此整成對象數組,然后監聽這些對象的某個字符串屬性就行了。
這個value值的變動,我們可以綁定$watch回調,當輸入值超過4個字符串時,進行跳轉操作。
el.$watch("value", function(a, b) { if (a.length >= 4) { model.focusIndex = index + 1 //跳轉 el.value = a.slice(0, 4) } })
如果實現跳轉操作呢,我們使用另一個新屬性focusIndex 來監聽,當它變化時,我們再調用一個跳轉方法。而這個跳轉方法需要得到元素節點。這唯有萬能綁定ms-bind 能干這事。
ms-bind="vmProp:vmCallback"
vmCallback的this指向被綁定元素,並傳入此綁定屬性的前后兩個值。vmProp的值每次變動都會調用vmCallback。
貼粘時,我們需要用到paste事件,但avalon默認沒此綁定,需要用ms-on傳入事件名,這里面做些兼容處理,逐一修改seriesNumber 數組對象的value 值就行了。
整個流程簡單利落,除了跳轉時我們用到一些DOM方法,其他都是對數據的操作。這與以往jQuery, Prototype.js, YUI的實現思路完全不同。打個比喻,avalon帶來的技術體驗,如同書法與打印機的區別。jQuery好優雅,能讓你精確控制每一步DOM操作,DOM操作越是復雜,如同繁體字那樣縱橫捭闔,越是顯得jQuery游刃有余。avalon好干凈,不要准備文房四寶,一張A4,一台打印機就行了,刷刷地出來你要的東西,干脆利落,沒什么人情味,但效率奇高,是工業革命的先聲。從歷史的發展過程來看,書法這種講究技術,滲雜着許多人個品味地藝術被整齊划一的印刷術逼到一死角,被剝奪了文化傳承者的角色。jQuery這些也一樣,DOM操作最快,也比不上MVVM這種印刷機般的技術,后者能不着痕跡地同步視圖,里面精密的算法保證不會存在冗余無用的DOM操作。前者還存在“糟糕的書法者”問題,最好的筆硯,在某些人手里也是潦草不堪,看守打印機工作就沒這問題。從勢利的角度來看,就是怎么能夠給資本家帶來好處,怎么在相對時間內能夠有更多更快, 更穩定的產出,就怎么快被采納,人性使然。
相關文章