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操作。前者還存在“糟糕的書法者”問題,最好的筆硯,在某些人手里也是潦草不堪,看守打印機工作就沒這問題。從勢利的角度來看,就是怎么能夠給資本家帶來好處,怎么在相對時間內能夠有更多更快, 更穩定的產出,就怎么快被采納,人性使然。
相關文章
