首页 > 解决方案 > 检测 html 元素更改的 jQuery 最佳实践

问题描述

我有两个运行良好的代码选项,但我想知道什么是最好的选择,假设我有时会在高流量网站中同时触发几个此脚本。

该代码用于限制输入复选框的选择,以下脚本仅用于 1 个部分,但我将在每个页面中同时检查 4 个或更多部分(我仍在编码循环检查,所以这里只是一个部分)。

选项1

    jQuery( function($){
        var max_opcoes = 2;
        var inputs_opcoes = "div.wc-pao-addon-container:has([data-addon-name='Opções']) input";
        $('body').on('change', inputs_opcoes, function(){
          var $inputs_opcoes = $(inputs_opcoes);

          if($inputs_opcoes.filter(':checked').length == max_opcoes) {
            $inputs_opcoes.attr('disabled', 'disabled');
            $inputs_opcoes.filter(':checked').removeAttr('disabled');
          } else {
            $inputs_opcoes.removeAttr('disabled');
          }

        });
    
    });

选项 2

jQuery( function($){
    var onDomIsRendered = function(domString) {
        return new Promise(function(resolve, reject) {
            function waitUntil() {
                setTimeout(function() {
                    if($(domString).length > 0){
                        resolve($(domString));
                    }else {
                        waitUntil();
                    }
                  }, 100);
                }
            //start the loop
            waitUntil();
        });
    };

    onDomIsRendered("div.wcpt-product-form.wcpt-modal").then(function(element){
        
        var max_opcoes = 2;
        var $inputs_opcoes = $("div:has([data-addon-name='Opções']) > input");
                        
        $inputs_opcoes.change(function() {
        //$( $inputs_opcoes ).on( 'change', function() {

          if($inputs_opcoes.filter(':checked').length == max_opcoes) {
            $inputs_opcoes.attr('disabled', 'disabled');
            $inputs_opcoes.filter(':checked').removeAttr('disabled');
          } else {
            $inputs_opcoes.removeAttr('disabled');
          }
        });

因此,两种代码的基本区别是:

$('body').on('change', inputs_opcoes, function(){
    (... function here ...)

    var onDomIsRendered = function(domString) {
        return new Promise(function(resolve, reject) {
            function waitUntil() {
                setTimeout(function() {
                    if($(domString).length > 0){
                        resolve($(domString));
                    }else {
                        waitUntil();
                    }
                  }, 100);
                }
            //start the loop
            waitUntil();
        });
    };

    onDomIsRendered("div.wcpt-product-form.wcpt-modal").then(function(element){
    (... function here ...)

标签: jquery

解决方案


你可能不应该像这样使用 setTimeout,因为它每 100 毫秒使用一次 CPU,而且我看不到这一点,因为从它的外观来看,当它到达 onDomIsRendered 时,jQuery 的 ready 事件已经被触发,所以有什么意义?

另一个观察是你应该使用 prop 而不是 attr 因为它更快。您还可以通过将“body”替换为 document.body 并将您的第一次调用保存到 $inputs_opcoes.filter(":checked") 来加速它。这就是我的意思:

jQuery( function($){
    var max_opcoes = 2, inputs_opcoes = 'div.wc-pao-addon-container:has([data-addon-name="Opções"]) input';
    $(document.body).on("change", inputs_opcoes, function(){
        var $inputs_opcoes = $(inputs_opcoes), $checked = $inputs_opcoes.filter(":checked");

        if ($checked.length == max_opcoes) {
            $inputs_opcoes.prop("disabled", true);
            $checked.prop("disabled", false);
        }
        else {
            $inputs_opcoes.prop("disabled", false);
        }
    });
});

Promise 在旧版浏览器中也不可用。如果你真的需要使用 jQuery 的 $.Deferred() ,它对于这么简单的事情来说已经足够好了。并使用 MutationObserver 代替 setTimeout。


推荐阅读