Skip to content

My Story / 我的故事 #11

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 的实际实现,请参阅文档和源码。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions