首页 > 解决方案 > 是否可以通过 Ajax 将内容更新给最终用户,而不会因更新/刷新而丢失滚动位置?

问题描述

这个问题被要求检查是否可以做我想做的事情,而不是如何做这个问题(尽管如果有人想写点什么也总是好的)。由于我的网络开发学习还处于起步阶段,所以我认为在投入大量时间来实现它之前确定是否有希望的结果是可能的。我从网络上的各种参考资料中阅读了相互矛盾的东西,并认为这是询问他人意见以确保一种或另一种方式的地方。

我正在运行 Drupal 8(撰写本文时为 8.9.13)。该页面使用视图。为简单起见,该页面有 3 个部分;顶部、中间和底部(这是页面/内容本身,这不是页眉、正文、页脚)。底部部分/视图由多个 div/部分组成。所有 3 部分的内容主要是链接。

我正在使用/尝试模块“视图自动刷新 D8”。在安装和设置之后,它会完美地更新页面,除了不仅在内容更新之后,而且在每次 Ajax 检查/间隔之后页面返回到页面顶部,导致用户体验不可接受。换句话说,如果读取页面底部,一旦页面通过 Ajax 自动检查更新,页面就会突然返回到页面顶部。

研究这个我得到的印象是 Ajax 的正常行为。我也觉得这种行为可以被覆盖,但是,其他来源使它听起来好像不能。因此,这个问题的目的在这里。

“Views Auto-Refresh D8”模块的 Javascript 如下所示:

(function ($, Drupal, drupalSettings) {
    // START jQuery

    Drupal.behaviors.views_autorefresh = {
        attach: function(context, settings) {
            for(var view_name in settings.views_autorefresh) {
                for(var view_display in settings.views_autorefresh[view_name]) {

                    var interval = settings.views_autorefresh[view_name][view_display];
                    var execution_setting = '.view-'+view_name.replace(new RegExp('_','g'),'-')+'.view-display-id-'+view_display;
                    if($(context).find(execution_setting).once(execution_setting).length > 0) {
                        // Delete timeOut before reset it
                        if(settings.views_autorefresh[view_name][view_display].timer) {
                            clearTimeout(settings.views_autorefresh[view_name][view_display].timer);
                        }
                        settings.views_autorefresh[view_name][view_display].timer = setInterval(
                            function() {
                                Drupal.behaviors.views_autorefresh.refresh(execution_setting)
                            }, interval
                        );
                    }
                }
            }
        },

        refresh: function(execution_setting) {
            $(execution_setting).trigger('RefreshView');
        }

    }

通过研究这个问题,我发现了密切相关的问题,说可以通过添加 javascript 函数来绕过/阻止页面刷新,例如:

preventDefault() / event.preventDefault()

但是我不完全确定是否可以使用此事件方法来实现我所追求的结果?或者如果以下是更好的探索途径?

我想出的另一个可能的解决方法/想法是我很好奇我使用了一个名为“Geysir”的模块,它允许我从前端直接在页面上更新我的内容。可以直接在页面上移动、删除内容,甚至可以在模式叠加层中修改内容,然后更新内容而无需“视图自动刷新 D8”正在执行的页面刷新/滚动回顶部。我想知道 Geysir 模块的逻辑是否可以应用于 Views Auto-Refresh D8 模块?以我适度的 javascript 知识看来,Geysir 模块中的相关 js/Ajax 逻辑是:

            $.each(Drupal.ajax.instances, function (index, event) {
              var element = $(event.element);
              if (element.hasClass('geysir-paste')) {
                if (href === event.element_settings.url) {
                  event.options.url = event.options.url.replace('/' + paragraph_id + '/', '/' + parent_id + '/');
                }
              }
            });
          });
        });

        return false;
      });
    }
  };

  Drupal.AjaxCommands.prototype.geysirReattachBehaviors = function() {
      Drupal.ajax.instances = Drupal.ajax.instances.filter(function(el) {
        return el;
    });

    Drupal.attachBehaviors();
  };

})(jQuery, Drupal, drupalSettings);

(第 40-64 行)

这几乎就是我在前进之前所处的位置。所以:

  1. 在进行 Ajax 调用以及通过 Ajax 更新内容时,甚至可以保持最终用户的滚动/页面位置吗?

如果是这样,

  1. 上面哪条途径最好追求,或者,还有一条我还没有遇到过的途径吗?

标签: javascriptajaxdrupal-8drupal-modulesdrupal-views

解决方案


推荐阅读