Skip to content

My Story / 我的故事 #11

@cssmagic

Description

@cssmagic

Video / 视频

Slides / 幻灯片

此分享的幻灯片实验性地采用了纯 JS 代码的形式。

// MY STORY ABOUT CLICK-EVENT-BINDING

// @CSSMAGIC



// BACKGROUND




// ONE DAY...

// REQUIREMENT: LUCKY DRAW?



var btn = document.getElementById('lucky-draw')

btn.onclick = function () {
    BX.luckyDraw()
}



// TRACKING?




btn.onclick = function () {
    BX.luckyDraw()
    BX.track('lucky-draw')
}



// BUT...




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...
})

// WHAT A MESS...




// EVENT DELEGATION?




$('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...
})
// ...

// NEED TO IMPROVE THIS!




// 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
        // ...
    }

})
// `ID`?




// 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
        // ...
    }
})
// NO UGLY 'switch'!




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


// USE CASE: CMUI




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!




// Q & A

// THX!



  • 幻灯片内的所有代码均为示意代码。
  • 关于 Action 的实际实现,请参阅文档和源码。

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions