从jQuery自定义触发器/绑定事件

时间:2015-09-29 19:44:22

标签: javascript jquery events javascript-events

我使用jQuery触发元素上的自定义事件,我希望事件处理程序能够将数据(以对象的形式)传递回调用它的方法。触发器和处理程序位于不同的范围和文件中,不能以传统方式合并或共享。 (触发器方法是我正在编写的实用程序库的一部分,事件处理程序是我的前端视图模板的一部分。)

我知道这段代码不起作用,,但我写的是为了说明我希望尝试的内容。该模式基于我在.NET中所做的工作。

var data = { foo: 'bar' }
element.trigger('some-event', data)
if(data.foo != 'bar')
    alert('someone changed foo!')

处理程序......

element.bind('some-event', function(event, data)
{
    if(some_condition)
        data.foo = 'biz'
});

具体实现对我来说并不重要,只要我没有重新安排我的代码以将triggerbind同时放在同一范围内。

如何从事件处理程序返回返回值?

修改

为了提供更多的上下文,触发方法负责获取和处理数据,最后将其作为标记呈现给页面。在此之前,它使用相同的已处理data对象引发自定义事件,以便应用程序的其他组件可以有机会对已处理的数据执行某些操作。

在某些情况下,事件处理程序修改该组数据或事件信号对于数据已被处理且不需要额外处理或呈现的触发方法将是有益的。

如下所示。在此示例中,处理程序可能会根据某些属性值更改数据的显示方式。它还可以选择以不同的方式呈现数据(例如input)而不是触发函数中的默认呈现(例如label)。

此实现是一个示例,但是从处理程序返回对象或修改处理程序中的数据以使触发方法可以访问它的最终目标对于我的实际项目来说是常见的。

var data = load_data();
element.trigger('loading_data', data);
if(data.abort_render!==true)
{
    element.append('<label>Foo</label>')
    element.append('<span>' + data.foo + '</span>')
}

处理程序......

element.bind('loading-data', function(event, data)
{
    if(data.is_password == true)
    {
        data.foo = '*******'   //changed property persisted to triggering method and processed normally
    }
    if(data.type == 'abc')
    {
        element.append('<input value="' + data.foo + '"/>');
        data.abort_render = true;   //signals to the triggering method that it should not render the data to the page
    }
}

1 个答案:

答案 0 :(得分:2)

有一种方法。以下是jQuery方法(在此答案中修改自示例2 https://stackoverflow.com/a/20707308/870729

// Refactor below for efficiency - replace 'body' with closest known container element
jQuery('body').on(element, function(event, data) {
    if (data.foo != 'bar') {
        alert('someone moved my foo!');
    }
});

要获得更强大的解决方案,请尝试以下方法:

// Bind the event to the element
jQuery('body').on(element, 'some-event', function(event, data) {
    // Call the callback function, pass in the data
    eventCallback(data);
});

// Call this function to set up the data and trigger the event
function triggerMyEvent() {
    var data = { foo: 'bar' };
    element.trigger('some-event', data); 
}

// The callback function set in the event binding above
function eventCallback(data) {
    if(data.foo != 'bar')
        alert('someone changed foo!');
}

挑战可能在于逻辑/代码的流程。以下是代码(来自您的问题) - 我添加了一些评论以尝试帮助解释流程:

// Command 1: This will run first
var data = load_data();
// Command 2: This will run second
element.trigger('loading_data', data);
// Command 3: This will run independently of the trigger callback
// and the data will not be modified based on the trigger.
// You will want to restructure your code to run this within the
// trigger callback
if(data.abort_render!==true)
{
    element.append('<label>Foo</label>')
    element.append('<span>' + data.foo + '</span>')
}

// Event handler (will run independently of Command 3)
jQuery('body').on(element, 'loading_data', function(event, data) {
    // THIS will run independently of the "Command 3" code above
    // and may or may not be done before Command 3 is run.
    // That's why this needs to trigger the code that handles
    // the data checks and various outputs based on the data
    handleLoadData(data);
}

// A specific function designed to be run AFTER event handler, 
// specifically to handle the various data settings that may be set.
function handleLoadData(data) {
    if(data.is_password == true) {
        data.foo = '*******'   //changed property persisted to triggering method and processed normally
    }

    if(data.type == 'abc') {
        element.append('<input value="' + data.foo + '"/>');
        data.abort_render = true;   //signals to the triggering method that it should not render the data to the page
    }

    // This code will need to be moved here, because data may 
    // not be updated when Command 3 is run above. Alternatively,
    // You could put it in another function, and call that function
    // from here.
    if(data.abort_render!==true) {
        element.append('<label>Foo</label>')
        element.append('<span>' + data.foo + '</span>')
    }
}

不会按照您期望的顺序运行。请参阅上面的评论以获取帮助