在 jQuery 插件中实现 $(this)

Posted

技术标签:

【中文标题】在 jQuery 插件中实现 $(this)【英文标题】:Implementing $(this) in a jQuery plugin 【发布时间】:2014-07-17 05:59:36 【问题描述】:

我一直在寻找在 jQuery 中开发一个长点击插件来处理这样的事件,经过大量研究,我找到了最好的方法。我在下面创建了插件。它不是一个大文件,但它涵盖了我需要的内容。不过还是有一些问题...

$(function($) 
  var holdTimer;
  $.fn.longclick = function( handler, time ) 
    if(time == undefined) time = 500;
    return this.mouseup(function()
      clearTimeout(holdTimer);
    ).mousedown(function()
      holdTimer = window.setTimeout(handler, time);
    );
  ;
  $.fn.longclick.defaultTime = 500;
(jQuery));

下面,我有测试它的页面:

// some markup
<input type="button" name="button3" id="button3" value="1500ms">

// and... the script itself

$("#button3").longclick( function() 
  var initial_text = $("#button3").val();
  console.log( $(this) );
  var initial_id = $(this).attr("id"); console.log( initial_id);
  var initial_html = $(this).html(); console.log(initial_html);
  $("#button3").replaceWith('<input type="textbox" id="" value=' + initial_text + '>');
, 1500);

现在,我的插件的问题似乎是它不知道$(this) 是什么意思。当我 console.log $(this) 它返回窗口本身,而不是我需要的按钮......另外,initial_idinitial_htmlundefined我怎样才能完成这项工作?

更新:initial_html 变量在我的例子中应该是 &lt;input type="button" name="button3" id="button3" value="1500ms"&gt;jQuery.html() 不会像我预期的那样工作,说 $(this).html()如何获取元素的 HTML?

【问题讨论】:

将控制台日志更改为警报。即 alert(initial_id) 和 alert(initial_html) 这将如何改变任何事情? 这会在警告框中显示一个准确的值。 除非我遗漏了什么,否则您的方法存在严重问题。如果我在按钮上mousedown 然后将鼠标从该按钮上移开并mouseup 怎么办?这不会在不应该触发的情况下触发长按吗? 如果你知道的话,你可以想出一个更好的方法:) 【参考方案1】:

setTimeout 内部,this 的值始终是窗口,而您正在从 setTimeout 函数的范围内调用回调。

$(function ($) 
    var holdTimer;
    $.fn.longclick = function (handler, time) 
        return this.on(
            mouseup : function () 
                clearTimeout(holdTimer);
            ,
            mousedown : function ()  
                var self  = this;
                holdTimer = window.setTimeout(function() 
                    handler.call(self);
                , time || $.fn.longclick.defaultTime);
            
        );
    ;
    $.fn.longclick.defaultTime = 500;
(jQuery));

您必须获取事件处理程序正在处理的元素,否则回调将应用于所有元素,请参阅此FIDDLE 以获取有关如何工作的示例。

【讨论】:

不一样,这在点击元素的回调中设置this,你在整个集合的回调中设置this,而你的只是一个编码转储,直到你更新它,我在小提琴中进行了一些缓慢的测试,以确保这是问题所在,并写了一个正确的答案。 @adeneo 在mousedown的回调中设置self的用例是什么? @IonicãBizãu - 嗯,只影响当前元素,并不是所有的元素都是我想的用例?【参考方案2】:

当您执行setTimeout(handler, time) 时,将从window 调用handlerthis 将等于window)。

因此,当您初始化插件实例时,您必须将 this 保存到 $self(它是一个 jQuery 对象)中。然后你必须这样做,而不是 setTimeout(handler, time)

holdTimer = window.setTimeout(function () 
    handler.call($self);
, time);

编辑后的插件是:

$(function($) 
  var holdTimer;
  $.fn.longclick = function( handler, time ) 
    var $self = this;
    if(time == undefined) time = 500;
    return this.mouseup(function()
      clearTimeout(holdTimer);
    ).mousedown(function()
        holdTimer = window.setTimeout(function () 
            handler.call($self);
        , time);
    );
  ;
  $.fn.longclick.defaultTime = 500;
(jQuery));

关于旧元素的 HTML,jQuery.html() 采用内部 HTML。您需要outerHTML。所以,你可以这样理解:$(this)[0].outerHTML

var initial_html = $(this)[0].outerHTML;
console.log(initial_html); // <input type="button" name="button3" id="button3" value="1500ms"> 

JSFIDDLE

【讨论】:

以上是关于在 jQuery 插件中实现 $(this)的主要内容,如果未能解决你的问题,请参考以下文章

jQuery 切换 Cookie 支持

如何使用jQuery在发票中实现折扣值

如何在javascript中实现分层多级数据表?

如何在 Flutter Dart 中实现插件架构

在setting中实现可拔插的插件功能实现

在 jsf<h:datatable 上在丰富的 fcaes 4 中实现 jquery