【问题标题】:Override jQuery .val() function?覆盖 jQuery .val() 函数?
【发布时间】:2010-01-13 20:15:33
【问题描述】:

有没有办法轻松覆盖 jQuery 的 val() 函数?

我想覆盖它的原因是我想在每次为元素设置值时添加一些处理。而且我不想制作另一个自定义值设置器,例如myVal()

【问题讨论】:

  • 我假设 .change() 事件在这里对你不起作用?
  • @Mark :当我通过 $('#foo').val('someValue') 设置元素的值时,不会触发 .change() 事件。只有当用户在 GUI/浏览器上更改值时才会触发它。
  • $('#foo').val('someValue').trigger('change');可能用于将触发器链接在那里......
  • @Mark:因为我需要在第一次将值存储到元素中时在任何地方进行这种特殊处理,所以我不想在每个元素中添加额外的 .trigger() 代码我使用 .val() 的地方。此外,如果我使用 .trigger() 那么这将无意中触发我不想运行的更改事件,该事件旨在处理来自 GUI 而不是代码本身的更改事件。覆盖 .val() CMS 发布的方式正是我需要做的:-)

标签: jquery jquery-plugins


【解决方案1】:

您可以存储对原始val 函数的引用,然后覆盖它并进行处理,然后使用call 调用它,以使用正确的上下文:

(function ($) {
  var originalVal = $.fn.val;
  $.fn.val = function(value) {
    if (typeof value != 'undefined') {
      // setter invoked, do processing
    }
    return originalVal.call(this, value);
  };
})(jQuery);

请注意,您可以通过检查 value 参数是否为 undefined 来区分 getter 调用 $(selector).val(); 和 setter 调用 $(selector).val('new value');

【讨论】:

  • 这行不通(至少在 jQuery 1.7 中不行)。原始 jQuery 函数依赖于参数计数,因此它会认为原始 val() 方法调用始终是一个 setter。要解决此问题,请替换“return originalVal.call(this, value);” with "return originalVal.apply(this, arguments);"
  • 原始版本和@dkl 提出的更改均不适用于 Chrome。使用 if..else 来测试您是否正在获取或设置是否有效。以下是透明覆盖,根据需要进行更改。 (function ($) { var originalVal = $.fn.val; $.fn.val = function(value) { if (typeof value == 'undefined') { return originalVal.call(this); } else { return originalVal .call(this, value); } }; })(jQuery);
  • 这是一个完美的答案,帮助我控制了 morris.js onHoverMove 事件以更改图例位置。对于返回 stmt,我写的 let afterOriginalFunc = originalVal.call(this,value); CallMyFunction_DependentOnThatExecution(); return afterOriginalFunc; 是执行原始函数并在该函数评估后立即触发我的依赖代码的完美代码。感谢您提供示例并分享解决方案。
【解决方案2】:

我知道这是一个古老的主题,但它在谷歌搜索中是第一个,答案并不完全正确......

例如,如果您在控制台中尝试$('#myinput').val(),您应该会得到#myinput 的值。

但是如果你这样做$('#myinput').val(undefined)你应该设置#myinput的值!( 使用当前答案和它的 cmets,您将不会设置 #myinput 的值)

这是使用arguments的升级答案。

(function ($) {
  var originalVal = $.fn.val;
  $.fn.val = function(value) {
    if (arguments.length >= 1) {
      // setter invoked, do processing
      return originalVal.call(this, value); 
    }
    //getter invoked do processing
    return originalVal.call(this);
  };
})(jQuery);

如果你想传递所有参数,你也可以使用 apply

(function ($) {
  var originalVal = $.fn.val;
  $.fn.val = function(value) {
    if (arguments.length >= 1) {
      // setter invoked, do processing
    } else {
      //getter invoked do processing
    }
    return originalVal.apply(this, arguments);
  };
})(jQuery);

希望对你有帮助!

【讨论】:

  • 很好的答案!完美运行。
  • 我已更新我的选择以获取已接受的答案。因为旧的答案已经过时了,因为其他人已经指出它不再有效。
【解决方案3】:

我知道这个问题很老,但只是为了给出一个完整的解决方案。为了让 jQuery.val() 和 jQuery.val(value) 在覆盖后工作,您需要正确地单独覆盖它。 因为当调用 jQuery.val() 然后 originalVal.call(this, value);将无法正常工作。

要以正确的方式执行此操作,您需要在获取值时执行类似的操作: originalVal.call(this);

这是一个解释一切的网站:http://extremedev.blogspot.com/2012/01/override-jqueryval-and-jqueryvalvalue.html

问候, 罗马

【讨论】:

  • 谢谢 Roman 我已经知道了,但是您在这里为您的网站做一些自我宣传。如果您至少还将完整答案粘贴到堆栈溢出中,那将更加有用。这样,如果您的网站从互联网上消失,您的答案仍然会在该网站上完整显示,供人们查看。那将是更有帮助的罗曼。不过感谢您的努力。
  • 如果该代码甚至可以工作,那就太好了!在您尝试使用 jQuery 解决之前,“widgetElementId”在哪里定义?
【解决方案4】:

如果我的理解是正确的,这样的事情应该可以解决问题:

jQuery.fn.val = function (new_val) {
    alert("You set a val! How wonderful!");
    this.value = new_val;
};

只需确保包含常规功能:获取选择值等。只需将代码 after 放在常规 jQuery 库之后。

【讨论】:

  • 不要复制原始行为,只需显式调用它以确保向前兼容以及与 val() 函数的其他覆盖兼容。
  • @Martijn:如果我两年前知道我现在所知道的,我会那样做的。但不幸的是,这有点晚了。
【解决方案5】:

使用此代码,您可以针对特定元素覆盖 .val() 的“get”和“set”:

(function () {

    var __val = $.fn.val;
    $.fn.val = function (value) {
        if (this[0] && (this[0].$val_get || this[0].$val_set)) {
            if (arguments.length === 0) return this[0].$val_get();
            else return this[0].$val_set(value) || this;
        }
        return __val.apply(this, arguments);
    };

})();

现在您必须在 DOM 元素上创建两个函数属性 - $val_get$val_set

<input type="text" id="myInput" />
<input type="text" id="someOtherInput" />

<script>

    $('#myInput')[0].$val_get = function () {
        console.log('Got value from myInput!');
        return this.value;
    };

    $('#myInput')[0].$val_set = function (value) {
        console.log('Set value of myInput!');
         this.value = value;
    }

    //----

    $('#myInput').val('Hello!'); //Console: "Got value from myInput!"
    $('#myInput').val(); //Hello! | Console: "Set value to myInput!"

    $('#someOtherInput').val('Hello!'); //Console: ""
    $('#someOtherInput').val(); //Hello! | Console: ""

</script>

这对于创建编排多个控件的组件很有用。

JsFiddle:https://jsfiddle.net/oj4gt2ye/6/

【讨论】:

    【解决方案6】:

    我有一些内容要添加到 CMS 答案中,我的实现会有所不同,如下所示:

    (function ($) { var fnVal = $.fn.val;
        $.fn.val = function(value) {
            if (typeof value == 'undefined') {
                return fnVal.call(this);
            }
            var result = fnVal.call(this, value);
            $.fn.change.call(this);
            // here you can add some more implementation
            return result;
        };
    })(jQuery);
    

    观察 $.fn.change.call(this); 将在退出 val('') 函数之前被调用,这也将触发每个 val('' 上的 .change() ) 分配。

    【讨论】:

      猜你喜欢
      • 2018-03-15
      • 2021-01-06
      • 2011-05-31
      • 1970-01-01
      • 1970-01-01
      • 2019-12-08
      • 1970-01-01
      • 2015-07-05
      相关资源
      最近更新 更多