前端頁面開發的很多情況下都需要實時監聽文本框輸入,比如騰訊微博編寫140字的微博時輸入框hu9i動態顯示還可以輸入的字數。過去一般都使用onchange/onkeyup/onkeypress/onkeydown實現,但是這存在着一些不好的用戶體驗。比如onchange事件只在鍵盤或者鼠標操作改變對象屬性,且失去焦點時觸發,腳本觸發無效;而onkeydown/onkeypress/onkeyup在處理復制、粘貼、拖拽、長按鍵(按住鍵盤不放)等細節上並不完善。
onpropertychange屬性可在某些情況下解決上面存在的問題,不用考慮是否失去焦點,不管js操作還是鍵盤鼠標手動操作,只要HTML元素屬性發生改變即可立即捕獲到。遺憾的是,onpropertychange為IE專屬的。其他瀏覽器下如果想要實現這一實時監聽的需求,就要用到HTML5中的標准事件oninput,不過IE9以下的瀏覽器是不支持oninput事件的。
所以我們需要綜合oninput和onpropertychange二者來實現文本區域實時監聽的功能。舉例如下:
例1、對支持oninput的瀏覽器用oninput,其他瀏覽器(IE6/7/8)使用onpropertychange:
var testinput = document.createElement('input'); if('oninput' in testinput){ object.addEventListener("input",fn,false); }else{ object.onpropertychange = fn; }
例2、對所有ie使用onpropertychange,其他瀏覽器用oninput:
var ie = !!window.ActiveXObject; if(ie){ object.onpropertychange = fn; }else{ object.addEventListener("input",fn,false); }
匯總onchange onpropertychange 和oninput事件的區別:
下面引用一篇譯文:
HTML5將oninput事件標准化了,該事件用來檢測用戶的輸入狀態。當然,通過使用onkeydown
或者onkeyup
作為代替也是可以的。這些事件設計本意也並非如此,參見詳情。
所有的現代瀏覽器支持oninput
,其中包括IE9。對於那些老式瀏覽器,在不支持該事件時用keydown
作為優雅降級。不幸的是,檢測瀏覽器對該oninput
事件的支持性並不容易。假定瀏覽器支持oninput
,那么以下這段js代碼的返回值為true
,否則為false
。
'oninput' in document.createElement('input')
這段代碼在大多數瀏覽器中正常運行,除了Firefox(見bug #414853),故仍舊需要為oninput作瀏覽器特性檢測。除此以外就沒必要為其他瀏覽器作特性檢測了,只需為input
和keydown
綁定事件,並在oninput
事件觸發之后刪除onkeydown
即可。示例如下:
someElement.oninput = function() {
el.onkeydown = null;
// Your code goes here
};
someElement.onkeydown = function() {
// Your code goes here
}
keydown
事件僅會被觸發一次(在oninput
事件觸發前),之后再觸發oninput
。雖然並不完美,但總比寫上一大堆oninput
特性檢測代碼要好些吧。
總結js方式:
function update() {
// Your code goes here, e.g.
console.log(this.value);
}
someElement.oninput = function() {
this.onkeydown = null;
update.call(this);
};
someElement.onkeydown = function() {
update.call(this);
};
jquery方式:
function update() {
// Your code goes here, e.g.
console.log(this.value);
}
var $someElement = $(someElement);
$someElement.bind({
'input': function() {
$someElement.unbind('keydown');
update.call(this);
},
'keydown': update
});
jquery插件方式:
$.fn.input = function(fn) {
var $this = this;
if (!fn) {
return $this.trigger('keydown.input');
}
return $this.bind({
'input.input': function(event) {
$this.unbind('keydown.input');
fn.call(this, event);
},
'keydown.input': function(event) {
fn.call(this, event);
}
});
};
使用:
$('.any-number-of-elements').input(function(event) {
alert(this.value);
event.preventDefault();
});
另外一種解決辦法是:
if (!("oninput" in document.body)) {
element.onpropertychange = function() {
if (event.propertyName == "value")
this.oninput && this.oninput(event);
}
}
element.oninput = function() {
// …
}