關於 JavaScript 的事件綁定在網上已經有不少相關的資料了
今天這篇文章也是在被同事問及的時候才順便把它記錄下來
算是 JavaScript 事件綁定中的一個小技巧
如果能在工作中善加利用
會有出其不意的效果
其實沒有什麼新的知識點只是為了方便其他有需要的朋友們翻閱對自己而言也算是一個積累所以只能算是閒談 JavaScript老鳥們可以盡情飄過
在進入正題之前先提個問題熱熱身吧
現在有如下 HTML 結構
復制代碼 代碼如下:
<div id="wrap">
<input type="button" value="按鈕一" />
<input type="button" value="按鈕二" />
<input type="button" value="按鈕三" />
<input type="button" value="按鈕四" />
<input type="button" value="按鈕五" />
</div>
以及如下 JavaScript 代碼
復制代碼 代碼如下:
var wrap = document
getElementById(
wrap
)
inputs = wrap
getElementsByTagName(
input
);
for (var i =
l = inputs
length; i < l; i++) {
inputs[i]
onclick = function () {
alert(i);
}
}
請問這樣執行的結果是什麼?
/***************************分割線***************************/
如果你的回答是“點擊按鈕時 alert 當前按鈕的索引值 i”那你就中了我的圈套了大家不妨試試無論你點擊哪個按鈕它都會alert()
這個看似理所當然的結果為什麼會和實際情況不同呢?其實也是很好理解的
因為 onclick 只是事件綁定而不是執行當我們執行 onclick 事件的時候這時的 i 已經是循環以後的值了照這樣看每個按鈕都alert() 也就不足為奇了
那麼如果我們要怎麼實現“點擊按鈕時alert 當前按鈕的索引值 i”呢?這裡就要用到 JavaScript 中暗藏玄機的一個概念“閉包”我們可以用閉包的方式改寫以上 JS把 for 循環中的 i 值保存在內存中代碼如下
復制代碼 代碼如下:
var wrap = document
getElementById(
wrap
)
inputs = wrap
getElementsByTagName(
input
);
for (var i =
l = inputs
length; i < l; i++) {
(function (cur) {
inputs[cur]
onclick = function () {
alert(cur);
}
})(i)
}
再試試效果?確實能 alert 出相應的索引值了不過至此為止還只是開胃菜正題才剛剛開始!
以 上的方法我們是通過循環 + 閉包給 button 按鈕上綁定事件我們知道在 JavaScript 中函數也是對象對象就會占用內存現在的例子中只有 個按鈕或許你會認為這樣的性能開銷可以忽略不計但是如果當我們有 個甚至 個按鈕的時候IE 已經哭了當有更多其他性能隱患並發時所有的浏覽器都哭了
回到剛才的例子我們可以用“事件委托”的方法來解決 這個因綁定事件隨著按鈕增加而可能導致的性能問題原理很簡單利用 Javascript 的事件冒泡我們可以把事件的綁定從按鈕移到它們的父級元素上不管按鈕有多少它們只有一個共同的父級元素那樣我們只需要綁定一次事件就可以了
代碼如下
復制代碼 代碼如下:
var wrap = document
getElementById(
wrap
)
inputs = wrap
getElementsByTagName(
input
);
wrap
onclick = function (ev) {
var ev = ev || window
event
target = ev
target || ev
srcElement;
for (var i =
l = inputs
length; i < l; i++) {
if (inputs[i] === target) {
alert(i)
}
}
}
至此正餐完畢我們還可以再深入一下來些餐後甜點
除了在性能上事件委托比閉包的事件綁定更有優勢以外事件委托還無需顧及子元素(即被綁定事件的元素)的數量比如我們在 onclick 事件綁定以後增加一個按鈕
復制代碼 代碼如下:
var newInput = document
createElement(
input
);
newInput
setAttribute(
type
button
);
newInput
setAttribute(
value
按鈕六
);
wrap
appendChild(newInput);
同 樣在最後加了這段代碼的閉包方式和事件委托方式我們可以看到閉包實現的事件綁定中點擊“按鈕六”毫無效果但是在事件委托中實現的事件綁定點擊“按鈕 六”則會有 alert相反如果我們要刪除一個按鈕閉包的方式仍會在內存中保存已刪除按鈕的 onclick 事件(除非手動設為 null)事件委托則不會對內存造成多余的負擔就為這個原因我們也應該多加利用事件委托的方式來綁定同一層級的多個元素
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/20249.html