JQuery / Javascript钩子

时间:2013-11-21 20:24:19

标签: javascript jquery events hook

我正在写一个附加组件。我需要在某些方面修改现有的javascript / jquery。它根据输入计算价格。伪代码(原始js我需要修改):

input.onEvent
    get Input Values
    calculate 'price' from input values

我需要修改计算出的价格。所以我需要以这样的方式修改原始的js:

    modified price = triggerEvent('modifyThePrice', price)

用语言:我需要调用一个钩子,然后其他的javascript就可以完成他们的工作并在需要时修改价格(或者像带有return语句的事件)......

根据要求我还会添加更精确的代码..

$('form#buy').bind('price-update', function(){
/*
* a LOT of code, getting input, calculating price. at the end we have a var 
*price which is numeric
*/

//What I need to do now
var modified_price = modifyPrice(price);
});

只是modifyPrice(price)必须调用页面上的每个其他js,这样每个人都有机会进行交互。

知道wordpress的那些人:我需要做一些可以用wp完成的事情:

$modified_price = apply_filters('modify_price', $price);

每个人都可以将函数绑定到'modify-price'钩子

我希望这有助于理解问题

2 个答案:

答案 0 :(得分:2)

这个怎么样?首先,过滤器模块:

var filter = {

    filters: {},

    add: function (tag, filter) {
        (this.filters[tag] || (this.filters[tag] = [])).push(filter);
    },

    apply: function (tag, val) {
        if(this.filters[tag]){
            var filters = this.filters[tag];
            for(var i = 0; i < filters.length; i++){
                val = filters[i](val);
            }
        }
        return val;
    }
}

然后添加过滤器:

filter.add('modify_name', function(name){
    name = 'MR. ' + name;
    return name;
});

并应用过滤器:

name = filter.apply('modify_name', name);

Jsfiddle demo

或者,以下是使用dom事件的方法:

$(window).on('modify_name', function (e, data) {
    data.name = 'MR. ' + data.name;
});

var data = {};
data.name = 'joe';
$(window).trigger('modify_name', data); 

注意:jQuery.trigger不会返回事件侦听器中的值,因此挂钩必须直接更改数据,而不是返回数据。此外,在Javascript中,除了对象之外,您无法通过引用传递值。因此,为了传递数据进行修改,我们必须先将它存储在一个对象中,然后将该对象传递给钩子。

Jsfiddle demo

答案 1 :(得分:0)

这个支持 namespace 的简单JavaScript钩子系统会将所有钩子函数存储在一个名为hooks的对象中:

&#13;
&#13;
var hooks = {}; // store all hooks here

function on(name, fn) {
    name = name.split('.');
    if (!hooks[name[0]]) hooks[name[0]] = {};
    var i = name[1] || Object.keys(hooks[name[0]]).length;
    hooks[name[0]][i] = fn;
}

function off(name) {
    if (!name) {
        return hooks = {};
    }
    name = name.split('.');
    if (name[1]) {
        delete hooks[name[0]][name[1]];
    } else {
        delete hooks[name[0]];
    }
}

function trigger(name, param) {
    name = name.split('.');
    if (!hooks[name[0]]) hooks[name[0]] = {};
    if (name[1]) {
        if (hooks[name[0]][name[1]]) hooks[name[0]][name[1]].apply({}, param);
    } else {
        for (var i in hooks[name[0]]) {
            hooks[name[0]][i].apply({}, param);
        }
    }
}
&#13;
<p>
  <button onclick="on('click',function(){alert('hook `'+(new Date()).getTime()+'` added!')});">Add a <code>click</code> Hook</button>
  <button onclick="on('click.foo',function(){alert('hook `click.foo` added!')});">Add a <code>click</code> Hook with ID <code>foo</code></button>
</p>
<p>
  <button onclick="off('click');">Remove All <code>click</code> Hooks</button>
  <button onclick="off('click.foo');">Remove a <code>click</code> Hook with ID <code>foo</code></button>
</p>
<p>
  <button onclick="trigger('click');">Trigger All <code>click</code> Hooks</button>
  <button onclick="trigger('click.foo');">Trigger <code>click</code> Hook with ID `foo`</button>
</p>
&#13;
&#13;
&#13;

用法

// add a `click` hook
on("click", function(x) {
    alert('test ' + x + ' ok!');
});

// add a `click` hook with `foo` namespace
on("click.foo", function(x) {
    alert('test ' + x + ' foo ok!');
});

// remove all `click` hooks
off("click");

// remove `click.foo` hook only
off("click.foo");

// trigger all `click` hooks
trigger("click", ['this will be the `x`', 'this will be the second function parameter…']);

// trigger `click.foo` hook only
trigger("click.foo", ['this will be the `x`', 'this will be the second function parameter…']);

如果要返回值,请改用此代码段:

var hooks = {}; // store all hooks here

function add_filter(name, fn) {
    name = name.split('.');
    if (!hooks[name[0]]) hooks[name[0]] = {};
    var i = name[1] || Object.keys(hooks[name[0]]).length;
    hooks[name[0]][i] = fn;
}

function remove_filter(name) {
    if (!name) {
        return hooks = {};
    }
    name = name.split('.');
    if (name[1]) {
        delete hooks[name[0]][name[1]];
    } else {
        delete hooks[name[0]];
    }
}

function apply_filter(name, value, param) {
    name = name.split('.');
    if (!hooks[name[0]]) hooks[name[0]] = {};
    if (name[1]) {
        if (hooks[name[0]][name[1]]) {
            value = hooks[name[0]][name[1]].apply(value, param);
        }
    } else {
        for (var i in hooks[name[0]]) {
            value = hooks[name[0]][i].apply(value, param);
        }
    }
    return value;
}

用法

// add a `test` filter
add_filter("test", function(v) {
    return v + ' test!';
});

// add a `test` filter with `foo` namespace
add_filter("test.foo", function(v) {
    return v + ' test.foo!';
});

// remove all `test` filters
remove_filter("test");

// remove `test.foo` filter only
remove_filter("test.foo");

// apply all `test` filters
return apply_filter("test", 'initial value', [param_1, param_2]);

// apply `test.foo` filter only
return apply_filter("test.foo", 'initial value', [param_1, param_2]);