强制重新激活ajaxed内容

时间:2017-08-11 03:24:50

标签: javascript ajax wordpress listener dom-events

TL;博士

我使用ajax来获取新内容。提取内容并将其添加到页面中。然而,剧本不会重新开始#34;因为他们的电话不在ajaxed div之内。

脚本在初始页面加载时加载和触发没有任何问题,但是当我通过ajax添加新内容时却没有。我没有控制台错误,如果我直接访问URL,则没有问题。

相关:

  1. Forcing Script To Run In AJAX Loaded Page - 与一个特定脚本相关。我想修复(重新发送)所有脚本,包括来自Cloudflare apps
  2. 的动态脚本
  3. Using jQuery script with Ajax in Wordpress - 与上述相同,这仅涉及一个特定的脚本
  4. ajax loaded content, script is not executing
  5. 说明:

    我在WordPress网站上使用Ajaxify WordPress Site(AWS)

    该插件允许您按其ID选择div,然后使用ajax <{1}}在div内获取新内容

    html标记

    <html>
    
    <head></head> 
    
    <body>
      <div id="page"> 
        <header></header>
        <main id="ajax"> <!-- This is what I want to ajaxify -->
          <div class="container">
            main page content
          </div> 
        </main> <!-- end of ajaxfied content  -->
        <footer></footer>
      </div> <!-- #page -->
    </body>
    
    </html>
    

    问题

    该插件有效,我可以加载和设置新内容,但存在问题。我的一些页面脚本和函数调用不在我使用ajax的div之外。我有两个例子

    1-加载Masonry并在<footer>

    中调用
    <html>
    
    <head></head> 
    
    <body>
      <div id="page"> 
        <header></header>
        <main id="ajax"> <!-- This is what I want to ajaxify -->
          <div class="container">
            main page content
          </div>  
        </main>   <!-- end of ajaxfied content  -->
        <footer></footer> <!-- Masonry script is loaded and called here -->
      </div> <!-- #page -->
    </body>
    
    </html>
    

    2- Google地图调用位于<head>

    <html>
    
    <head></head>  <!-- Google maps is called here -->
    
    <body>
      <div id="page"> 
        <header></header>
        <main id="ajax"> <!-- This is what I want to ajaxify -->
          <div class="container">
            main page content
          </div>  
        </main>  <!-- end of ajaxfied content  -->
        <footer></footer> 
      </div> <!-- #page -->
    </body>
    
    </html>
    

    这只是两个示例。其他地方还有其他人。正如您所知,这些脚本不会被重新调用,因为在页面上重新加载的唯一内容是<main id="ajax">。虽然 <main>中的新内容是,但是正确渲染它所需的一些脚本不会被重新调用,因此我最终会丢失元素/破坏布局。

    我不是唯一一个遇到过这个问题的人;快速查看插件的support forum on wordpress.org表明此问题很常见。

    注意:如果插件有许多其他问题,我不会尝试修复此问题。它对我有用我只需要脚本重新启动。

    官方回应是,可以通过在插件的php文件中添加以下内容来重新加载/重新激活脚本:

    $.getScript(rootUrl + 'PATH TO SCRIPT');
    

    哪个有效。它运作良好。例如,如果我添加

    $.getScript(rootUrl + '/Assets/masonry.js');
    

    然后,即使在ajaxed div

    之外加载了masonry.js,也会在获取ajaxed内容时重新触发砌体函数调用

    我建议您使用plugin's files on github以更清楚地了解修复程序的实际功能(我无法理解使用$.getScript时会发生什么)

    总结

    如果您需要在ajaxed内容上重新触发3-4个脚本,那么官方修复工作正常。

    这对我的目标不起作用,因为

    1. 它太僵硬且硬编码
    2. 部分脚本通过Cloudflare apps
    3. 动态添加到页面中

      可能的解决方案可能涉及添加一个模仿触发器的事件,该触发器会导致脚本在ajaxed div

      的底部触发

      问题:

      当只通过ajax重新加载页面的某个部分时,如何强制所有脚本 - 包括动态添加的 - 重新触发?

      注意:

      1. 我试图避免逐个调出脚本,因为这需要事先知道他们的调用。我可能在我脑海里说话但是......

        我正在尝试模仿页面加载和/或文档就绪事件 - 大多数条件脚本被触发(如果我错了,请纠正我) - 在我的html中<main>的末尾添加了新的ajaxed内容但是在通过直接使用url加载页面时不会影响文档。或任何其他类似的方法。

      2. 只是为了一些上下文,这里是一个列表,其中包含插件关闭时的一些事件监听器。我知道那里有些东西我不会被触发。我刚刚添加了这个作为参考。另请注意,这是从其中一个页面中提取的样本。其他页面可能不同。

      3. &#13;
        &#13;
        DOMContentLoaded
        beforeunload
        blur
        click
        focus
        focusin
        focusout
        hashchange
        keydown
        keyup
        load
        message
        mousedown
        mousemove
        mouseout
        mouseover
        mouseup
        mousewheel
        orientationchange
        readystatechange
        resize
        scroll
        submit
        touchscreen
        unload
        &#13;
        &#13;
        &#13;

7 个答案:

答案 0 :(得分:15)

您在此处选择的解决方案必须依赖于脚本的初始化方式。有几种常见的可能性:

  1. 加载脚本后会立即激活脚本的操作。在这种情况下,脚本可能如下所示:

    (function() {
         console.log('Running script...');
    })();
    
  2. 响应某些事件(例如文档就绪(JQuery)或窗口载入(JavaScript)事件),会引发脚本的操作。在这种情况下,脚本可能如下所示:

    $(window).on('load', function() {
        console.log('Running script...');
    });
    
  3. 下面考虑这两种可能性的一些选择。

    对于在加载时立即运行的脚本

    一种选择是从DOM中删除要触发的<script>元素,然后重新附加它们。使用JQuery,你可以做到

    $('script').remove().appendTo('html');
    

    当然,如果上面的代码段本身位于<script>标记中,那么您将创建一个无限循环,不断分离并重新附加所有脚本。此外,可能还有一些您不想重新运行的脚本。在这种情况下,您可以向脚本添加类以正面或负面地选择它们。例如,

    // Positively select scripts with class 'reload-on-ajax'
    $('script.reload-on-ajax').remove().appendTo('html');
    
    // Negatively select scripts with class 'no-reload'
    $('script').not('no-reload').remove().appendTo('html')
    

    在您的情况下,您可以将上述代码段中的一个放在事件处理程序中以完成AJAX。下面的示例使用按钮单击代替AJAX完成事件,但概念是相同的(请注意,此示例在StackOverflow沙箱中不能正常工作,因此请尝试将其作为单独的页面加载以获得最佳效果结果):

    &#13;
    &#13;
    <html>
      <head></head>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    
      <script class="reload-on-ajax">
        console.log('Script after head run.');
      </script>
    
      <body>
        <button id="reload-scripts-button">Reload Scripts</button>
      </body>
    
      <script class="reload-on-ajax">
        console.log('Script after body run.');
      </script>
    
      <script>
         $('#reload-scripts-button').click( () => $('script.reload-on-ajax').remove().appendTo('html') );
      </script>
    </html>
    &#13;
    &#13;
    &#13;

    请注意,如果脚本不是内联的(例如,通过src属性获取),则它们将从服务器重新加载或从浏览器缓存中检索,具体取决于浏览器和设置。在这种情况下,最好的方法可能是删除对加载AJAX的内容进行操作的所有<script>,并通过AJAX的getScript()函数加载/运行它们完成事件处理程序这样,您只需在适当的时间(即加载AJAX内容后)加载/运行脚本一次:

    // In AJAX success event handler
    $.getScript('script1.js');
    $.getScript('script2.js');
    

    此方法的两种变体的潜在问题是脚本的异步加载受到跨源限制。因此,如果脚本托管在不同的域上,并且不允许跨源请求,那么它将无法工作。

    对于为响应事件而运行的脚本

    如果脚本是在窗口加载时触发的,那么您可以触发此事件:

       $(window).trigger('load');
    

    不幸的是,如果脚本本身使用JQuery的文档就绪事件,那么我不知道手动触发它的简单方法。脚本也可能响应其他事件而运行。

    显然,您可以根据需要结合上述方法。并且,正如其他人所提到的,如果脚本中有一些初始化函数可以调用,那么这是最干净的方法。

答案 1 :(得分:5)

如果您可以在外部脚本中识别全局初始化函数或代码块,则可以查看“ajaxComplete”事件。您可以将此代码放在页头中,并将初始化函数调用或代码块放在ajaxComplete回调中。

$(document).ajaxComplete(function(){
    module1.init();
    $('#my_id').module2_init({
        foo : 'bar',
        baz : 123
    });
});

当您谈论的脚本没有这样易于使用的公开初始化函数,但是在脚本加载时初始化时,我认为没有适用于所有脚本的开箱即用方法。

答案 2 :(得分:5)

Here's what you can try -

Most of the scripts like masonry or Google Map are set to re-init on window resize. So, if you trigger the resize event after ajax complete, it will help to re-fire those scripts automatically.

Try the following code -

$( document ).ajaxComplete( function() {
    $( window ).trigger('resize');
} );

This will force the scripts to re-init once ajax is completed as it will now trigger the resize event after the content is loaded.

答案 3 :(得分:4)

解决方案可能是复制所有脚本......

;with tbl1
as
(
select a,sum(col1) as summ
from
tbl1
)
,tbl2
as
(
select userid,sum(Anothersmcol) as sum2
from tbl2

)
select tbl1.columns,tbl2.columns
from
tbl1 t1
join
tbl2 t2
on t1.sumcol>t2.sumcol

答案 4 :(得分:4)

可能存在风险,但您应该可以在DOMSubtreeModified元素上使用<main>

$('#ajaxed').bind('DOMSubtreeModified', function(){
  //your reload code
});

然后您应该能够在重装区域中再次附加所有脚本

var scripts = document.getElementsByTagName('script');
for (var i=0;i<scripts.length;i++){
   var src = scripts[i].src;
   var sTag = document.createElement('script');
   sTag.type = 'text/javascript';
   sTag.src = src;
   $('head').append(sTag);

}

另一个选项可能是创建自己的事件侦听器并在其中包含相同的重新加载代码。

$(document).on('ajaxContentLoaded', function(){//same reload code});

然后,一旦内容更新,您就可以在插件中触发事件。

$(document).trigger('ajaxContentLoaded');

或者可能是编辑插件以触发侦听器并添加到您的代码库以重新运行您认为需要重新运行该侦听器的任何内容的组合,而不是重新加载任何内容。

$(document).on('ajaxContentLoaded', function(){
   //Javascript object re-initialization
   myObj.init();
   //Just a portion of my Javascript?
   myObj.somePortion();
});

答案 5 :(得分:4)

在尝试使用ajax在wordpress中使用浏览器状态和history.js重新加载页面时,我遇到了这个问题。我直接将history.js排队,而不是使用插件为我做这件事。

每当点击一个新页面时,我就需要“重新运行”大量的JS。为此,我在名为global_scripts();

的主要javascript文件中创建了一个全局函数

首先,确保这个JS文件在footer.php之后排队。

看起来像这样:

wp_enqueue_script('ajax_js', 'url/to/file.js', 'google-maps', 1, true);

我排队的javascript是在下面。

jQuery(document).ready(function($) {

    // scripts that need to be called on every page load
    window.global_scripts = function(reload) {


       // Below are samples of the javascript I ran that I needed to re run.
       // This includes lazy image loading, paragraph truncation.

       /* I would put your masonry and google maps code in here. */

        bLazy = new Blazy({
            selector: '.featured-image:not(.no-blazy), .blazy', // all images
            offset: 100
        });


        /* truncate meeeee */
        $('.post-wrapper .post-info .dotdotdot').dotdotdot({
            watch: 'window'
        });

    }

    // call the method on initial page load (optional)
    //global_scripts();

});

然后我连接到每当页面加载了history.js并且调用global_scripts()时运行的JS;

您使用的插件似乎也使用history.js。我没有专门用你的插件测试它,但你可以尝试我在下面发布的内容(这是我在我的应用程序中使用的)。   这将在上面的相同JS文件中。

History.Adapter.bind(window, 'statechange', function() { 
     global_scripts();
}

我的代码比上面简单粘贴的代码复杂一点。我实际上检查事件以确定正在加载什么内容,并基于此加载特定的JS函数。它允许更多地控制重新加载的内容。

注意:我在声明函数时使用window.global_scripts,因为我有单独的JS文件来保存这段代码。如果它们全部相同,您可以选择删除它。

注意2:我意识到这个答案需要确切知道需要重新加载的内容,因此它忽略了你的最后一个注释,它要求这不需要这样的知识。它可能仍然可以帮助您找到答案。

答案 6 :(得分:3)

简短回答: 这是不可能的通用方式。您的脚本应该如何知道需要触发哪些事件?

更长的回答: 它更像是一个结构性问题,而不是一个程序性问题。谁负责所需的功能?让我们以砖石为例:

Masonry.js本身不会听任何事件。您需要自己创建一个砌体实例(这很可能是在您的Wordpress插件中完成的)。如果启用resize选项,它将为resize事件添加一个侦听器。但你真正想要的是一些倾听者&#34; DOM内容改变&#34; (有关可能的解决方案,请参阅https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver)。由于masonry.js不提供此类功能,因此您有以下选项:

  1. 等待实施(或自己动手)在masonry.js
  2. 等待在砌筑Wordpress插件中实现(或自己动手)。
  3. 在其他地方添加功能(您的模板,您的ajax插件等)
  4.  4。

    正如您所看到的,每个选项都包含一些要完成的工作,并且需要为您想要监听AJAX调用的DOM更改的每个脚本执行此项工作。