Video / 视频
Slides / 幻灯片
此分享的幻灯片实验性地采用了纯 JS 代码的形式。
// MY STORY ABOUT CLICK-EVENT-BINDING
// @CSSMAGIC
// ONE DAY...
// REQUIREMENT: LUCKY DRAW?
var btn = document.getElementById('lucky-draw')
btn.onclick = function () {
BX.luckyDraw()
}
btn.onclick = function () {
BX.luckyDraw()
BX.track('lucky-draw')
}
btn.onclick = function () {
BX.luckyDraw()
}
// some code...
btn.onclick = function () {
BX.track('lucky-draw')
}
btn.addEventListener('click', function () {
BX.luckyDraw()
}, false)
// some code...
btn.addEventListener('click', function () {
BX.track('lucky-draw')
}, false)
// A/B TEST?
// HALF OF USERS HAVE NO BTN?
var btn = document.getElementById('lucky-draw')
// A FIFTY-FIFTY CHANCE:
btn === null
if (btn) {
btn.addEventListener('click', function () {
BX.luckyDraw()
}, false)
}
// some code...
if (btn) {
btn.addEventListener('click', function () {
BX.track('lucky-draw')
}, false)
}
// "USE JQUERY, YOU IDIOT!"
var $btn = $('#lucky-draw')
$btn.on('click', function () {
BX.luckyDraw()
})
// some code...
$btn.on('click', function () {
BX.track('lucky-draw')
})
// SO FAR SO GOOD!
// BUT...
// SPA?
// HTML LAZY LOAD?
// HTML RENDERED BY JS?
$('.tabs > .surprise').on('click', function () {
var htmlTab = [
'<div>',
'<button id="lucky-draw">Lucky Draw</button>',
'</div>'
].join('')
$('.tab-panels > .surprise').html(htmlTab)
// EVENT-BINDING HERE...
})
$('body').on('click', '#lucky-draw', function () {
BX.luckyDraw()
})
// WHAT IF MORE AND MORE BTNS?
$body = $('body')
$body.on('click', '#lucky-draw', function () {
BX.luckyDraw()
})
$body.on('click', '#some-btn', function () {
// do something...
})
$body.on('click', '#another-btn', function () {
// do something else...
})
// ...
// GROUP ALL THESE EVENT DELEGATION?
// FIRST, THE SAME CLASS NAME.
var btn1 = '<button class="action" id="lucky-draw">Lucky Draw</button>'
var btn2 = '<button class="action" id="some-action">Button</button>'
var link1 = '<a href="#" class="action" id="another-action">Link</a>'
var link2 = '<a href="#" class="action" id="another-action-2">Link</a>'
// THEN, ONLY ONE LISTENER.
$body.on('click', '.action', function () {
// WHEN CLICK ANY '.action', WE COME HERE.
})
$body.on('click', '.action', function () {
// DISPATCH ACTION
// USE `id` TO IDENTIFY EACH BTN...
switch (this.id) {
case 'lucky-draw':
BX.luckyDraw()
break
case 'some-btn':
// do something...
break
// ...
}
})
// WHY NOT HTML5 DATASET?
// USE A CUSTOM DATA ATTRIBUTE -- 'data-action'!
var btn1 = '<button class="action" data-action="lucky-draw">Lucky Draw</button>'
var btn2 = '<button class="action" data-action="some-action">Button</button>'
var link1 = '<a href="#" class="action" data-action="another-action">Link</a>'
var link2 = '<a href="#" class="action" data-action="another-action-2">Link</a>'
// WAIT, CLASS NAMES ARE UNNECESSARY!
// SIMPLIFIED!
var btn1 = '<button data-action="lucky-draw">Lucky Draw</button>'
var btn2 = '<button data-action="some-action">Button</button>'
var link1 = '<a href="#" data-action="another-action">Link</a>'
var link2 = '<a href="#" data-action="another-action-2">Link</a>'
$body.on('click', '[data-action]', function () {
var actionName = $(this).data('action')
switch (actionName) {
case 'lucky-draw':
BX.luckyDraw()
break
case 'some-btn':
// do something...
break
// ...
}
})
var actionList = {
'lucky-draw': function () {
BX.luckyDraw()
},
'some-btn': function () {
// do something...
}
// ...
}
$body.on('click', '[data-action]', function () {
var actionName = $(this).data('action')
var action = actionList[actionName]
if ($.isFunction(action)) action()
})
// DEFINE MORE ACTION LATER?
// HTML
$body.append('<a href="#" data-action="more">Link</a>')
// JS
$.extend(actionList, {
'more': function () {
// ...
}
})
// MAYBE THIS FITS MORE PEOPLE...
// OPEN-SOURCE IT!
// `ACTION`
// EASY AND LAZY SOLUTION FOR CLICK-EVENT-BINDING.
// GITHUB: CSSMAGIC/ACTION
// API
// DEFINE ACTIONS
action.add({
'my-action': function () {
// ...
}
// ...
})
// TRIGGER ACTION MANUALLY
action.trigger('my-action')
// WHO'S USING IT?
// CMUI USES `ACTION` AS A CORE SERVICE.
// GITHUB: CMUI/CMUI
// EVERYONE USING CMUI IS USING `ACTION`:
// - M.BAIXING.COM
// - M.VICHY.COM.CN
// - M.UEMALL.COM
CMUI.dialog = {
template: [
'<div class="dialog">',
'<a href="#" data-action="close-dialog">×</a>',
'<h2><%= data.title %></h2>',
'<div class="content"><%- data.html %></div>',
'</div>'
].join(''),
init: function () {
action.add({
'close-dialog': function () {
$(this).closest('.dialog').hide()
}
})
},
open: function (config) {
var html = render(this.template, config)
$(html).appendTo('body').show()
}
}
// NO EVENT-BINDING CODE NEEDED!
注:
- 幻灯片内的所有代码均为示意代码。
- 关于 Action 的实际实现,请参阅文档和源码。