此AJAX代码不起作用-寻找优雅的解决方案

时间:2019-03-07 作者:user5854648

我试图在我的WordPress站点上使用AJAX作为用户滚动的帖子。我跟着this 但它对我的WordPress网站没有影响。

我使用了一个可以工作的插件,但我更愿意在没有插件的情况下学习如何做到这一点,既要学习,又要避免使用不必要的插件。下面的代码不起作用,尽管每页的帖子数设置为5,但我的所有帖子都会显示在页面上。

感谢您的帮助!

functions.php

function misha_my_load_more_scripts() {

    global $wp_query; 
    wp_enqueue_script(\'jquery\');
    wp_register_script( \'my_loadmore\', get_stylesheet_directory_uri() . \'/js/myloadmore.js\', array(\'jquery\') );

    wp_localize_script( \'my_loadmore\', \'misha_loadmore_params\', array(
        \'ajaxurl\' => site_url() . \'/wp-admin/admin-ajax.php\',
        \'posts\' => json_encode( $wp_query->query_vars ), 
        \'current_page\' => get_query_var( \'paged\' ) ? get_query_var(\'paged\') : 1,
        \'max_page\' => $wp_query->max_num_pages
    ) );

    wp_enqueue_script( \'my_loadmore\' );
}

add_action( \'wp_enqueue_scripts\', \'misha_my_load_more_scripts\' );

function misha_loadmore_ajax_handler(){

      $args = array(
      \'cat\' => -21,
      \'post_type\' => \'post\',
      \'posts_per_page\' => 5,
      \'paged\' => 1,
      \'tax_query\'      => array(
        array(
            \'taxonomy\' => \'topics\',
            \'operator\' => \'NOT EXISTS\'
        )
    )

    );
      $args = json_decode( stripslashes( $_POST[\'query\'] ), true );
      $args[\'paged\'] = $_POST[\'page\'] + 1; //need next page to be loaded
      $args[\'post_status\'] = \'publish\';

    $the_query = new WP_Query ( $args ); 

    if($the_query->have_posts()) : 
      while($the_query->have_posts()) : 
         $the_query->the_post();

    get_template_part( \'template-parts/post/content\', get_post_format() );

        endwhile;

    endif;
    die; 
}

add_action(\'wp_ajax_loadmore\', \'misha_loadmore_ajax_handler\'); // wp_ajax_{action}
add_action(\'wp_ajax_nopriv_loadmore\', \'misha_loadmore_ajax_handler\'); // wp_ajax_nopriv_{action}

myloadmore.js

jQuery(function($){
    var canBeLoaded = true, 
        bottomOffset = 2000; //I\'ve played with this number to see if it was the offset calling posts too soon but it has no effect 

    $(window).scroll(function(){
        var data = {
            \'action\': \'loadmore\',
            \'query\': misha_loadmore_params.posts,
            \'page\' : misha_loadmore_params.current_page
        };
        if( $(document).scrollTop() > ( $(document).height() - bottomOffset ) && canBeLoaded == true ){
            $.ajax({
                url : misha_loadmore_params.ajaxurl,
                data:data,
                type:\'POST\',
                beforeSend: function( xhr ){
                    canBeLoaded = false; 
                },
                success:function(data){
                    if( data ) {
                        $(\'#main\').find(\'div:last-of-type\').after( data ); 
                        canBeLoaded = true; 
                        misha_loadmore_params.current_page++;
                    }
                }
            });
        }
    });
});
<div class="row">
 <div class="col-sm-6">
    <?php $image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), \'single-post-thumbnail\' ); ?>
    <a href="<?php the_permalink(); ?>"><img src="<?php echo $image[0]; ?>" class="img-fluid"></a>
  </div>

  <div class="col-sm-6">

    <?php
      $categories = get_the_category();
        if ( $categories ) :
            $deepChild = get_deep_child_category( $categories );
    ?>
    <p><?php echo $deepChild->name; ?></p>

      <?php endif; ?>

      <h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>

  </div>
</div><!-- END ROW-->

front-page.php

<div id="main" class="container-fluid">
  <?php misha_loadmore_ajax_handler(); ?>
</div><!-- END CONTAINER -->
UPDATED CODE

以下是基于答案的更新代码。我之所以发布这篇文章,是因为它仍然不起作用,我可能忽视了/误解了一些东西,我想知道我错在哪里了。

functions.php

function misha_my_load_more_scripts() {
    wp_register_script( \'my_loadmore\', get_stylesheet_directory_uri() . \'/js/myloadmore.js\',
        array( \'jquery\' ), \'\', true );
    wp_enqueue_script( \'my_loadmore\' );
}
add_action( \'wp_enqueue_scripts\', \'misha_my_load_more_scripts\' );

function misha_loadmore_ajax_handler() {
    $args = json_decode( wp_unslash( $_POST[\'query\'] ), true );
    $args[\'paged\'] = $_POST[\'page\'] + 1; // load the next page

    $the_query = new WP_Query( $args );

    if ( $the_query->have_posts() ) :
        while ( $the_query->have_posts() ) : $the_query->the_post();
            get_template_part( \'template-parts/content\', get_post_format() );
        endwhile;
    endif;

    wp_die();
}
add_action( \'wp_ajax_loadmore\', \'misha_loadmore_ajax_handler\' );        // Authenticated users
add_action( \'wp_ajax_nopriv_loadmore\', \'misha_loadmore_ajax_handler\' ); // Non-authenticated users

myloadmore.js

jQuery(function($){
    var canBeLoaded = true, // this param allows to initiate the AJAX call only if necessary
        // the distance (in px) from the page bottom when you want to load more posts,
        bottomOffset = ( $( \'#main > div.post:last\' ).offset() || {} ).top;

    $(window).scroll(function(){
        if ( misha_loadmore_params.current_page >= misha_loadmore_params.max_page ) {
//          console.log( \'max_page reached; AJAX canceled\' );
            return; // we\'ve already reached the last page, so let\'s do no more AJAX.
        }
        var data = {
            \'action\': \'loadmore\',
            \'query\': misha_loadmore_params.posts,
            \'page\' : misha_loadmore_params.current_page
        };
        if( $(document).scrollTop() > ( $(document).height() - bottomOffset ) && canBeLoaded == true ){
            $.ajax({
                url : misha_loadmore_params.ajaxurl,
                data: data,
                type: \'POST\',
                beforeSend: function( xhr ){
                    // you can also add your own preloader here
                    // you see, the AJAX call is in process, we shouldn\'t run it again until complete
                    canBeLoaded = false;
                },
                success:function(data){
                    if( data ) {
                        $(\'#main\').find(\'div.post:last-of-type\').after( data ); // where to insert posts
                        canBeLoaded = true; // the ajax is completed, now we can run it again
                        misha_loadmore_params.current_page++;

                        bottomOffset = ( $( \'#main > div.post:last\' ).offset() || {} ).top
                    }
                }
            });
        }
    });
});
<div class="row">
 <div class="col-sm-6">
    <?php $image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), \'single-post-thumbnail\' ); ?>
    <a href="<?php the_permalink(); ?>"><img src="<?php echo $image[0]; ?>" class="img-fluid"></a>
  </div>

  <div class="col-sm-6">

    <?php
      $categories = get_the_category();
        if ( $categories ) :
            $deepChild = get_deep_child_category( $categories );
    ?>
    <p><?php echo $deepChild->name; ?></p>

      <?php endif; ?>

      <h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>

  </div>
</div><!-- END ROW-->

front-page.php

 <?php
  $current_page = max( 1, get_query_var( \'paged\' ) );
  $the_query = new WP_Query( array(
    \'cat\'            => \'-21\',
    \'post_type\'      => \'post\',
    \'posts_per_page\' => 5,
    \'paged\'          => $current_page,
  ) );

  wp_localize_script( \'my_loadmore\', \'misha_loadmore_params\', array(
    \'ajaxurl\'      => admin_url( \'admin-ajax.php\', \'relative\' ),
    \'posts\'        => json_encode( $the_query->query_vars ),
    \'current_page\' => $current_page,
    \'max_page\'     => $the_query->max_num_pages
  ) );
?>
  <div id="main" class="container-fluid">
    <?php
      if ( $the_query->have_posts() ) :
          while ( $the_query->have_posts() ) : $the_query->the_post();
              // Should match the one in misha_loadmore_ajax_handler().
              get_template_part( \'template-parts/content\', get_post_format() );
          endwhile;
      endif;
    ?>
  </div>

<?php wp_reset_postdata(); ?>

</div><!-- END CONTAINER -->

2 个回复
最合适的回答,由SO网友:Sally CJ 整理而成

工作代码基于我之前的答案,不使用nonce。。但是您可以检查前面关于如何实现nonce检查的答案并且代码基于您的代码。

misha_my_load_more_scripts() 在里面functions.php

function misha_my_load_more_scripts() {
    wp_register_script( \'my_loadmore\', get_stylesheet_directory_uri() . \'/js/myloadmore.js\',
        array( \'jquery\' ), \'\', true );
    wp_enqueue_script( \'my_loadmore\' );
}
add_action( \'wp_enqueue_scripts\', \'misha_my_load_more_scripts\' );

misha_loadmore_ajax_handler() 在里面functions.php

function misha_loadmore_ajax_handler() {
    $args = json_decode( wp_unslash( $_POST[\'query\'] ), true );
    $args[\'paged\'] = $_POST[\'page\'] + 1; // load the next page

    $the_query = new WP_Query( $args );

    if ( $the_query->have_posts() ) :
        while ( $the_query->have_posts() ) : $the_query->the_post();
            get_template_part( \'template-parts/post/content\', get_post_format() );
        endwhile;
    endif;

    wp_die();
}
add_action( \'wp_ajax_loadmore\', \'misha_loadmore_ajax_handler\' );        // Authenticated users
add_action( \'wp_ajax_nopriv_loadmore\', \'misha_loadmore_ajax_handler\' ); // Non-authenticated users

front-page.php (the#main 部门)

$current_page = max( 1, get_query_var( \'paged\' ) );
$the_query = new WP_Query( array(
    \'cat\'            => \'-21\',
    \'post_type\'      => \'post\',
    \'posts_per_page\' => 5,
    \'paged\'          => $current_page,
) );

wp_localize_script( \'my_loadmore\', \'misha_loadmore_params\', array(
    \'ajaxurl\'      => admin_url( \'admin-ajax.php\', \'relative\' ),
    \'posts\'        => json_encode( $the_query->query_vars ),
    \'current_page\' => $current_page,
    \'max_page\'     => $the_query->max_num_pages
) );
?>
    <div id="main" class="container-fluid">
        <?php
            if ( $the_query->have_posts() ) :
                while ( $the_query->have_posts() ) : $the_query->the_post();
                    // Should match the one in misha_loadmore_ajax_handler().
                    get_template_part( \'template-parts/post/content\', get_post_format() );
                endwhile;
            endif;
        ?>
    </div>
<?php
wp_reset_postdata();

myloadmore.jscontent.php

实际上,在我的代码(我实际测试的代码)中更新,I don\'t have the tax_query parameter, 但我在这个答案的前一个版本(不是本页的另一个版本)中错误地将其包含在上面的代码中。

因为tax_query 如下所示&mdash;未指定所需的terms parameter &mdash;将导致0 = 1 在MySQL查询中,并最终导致没有结果(即没有帖子):

$the_query = new WP_Query( array(
    ...
    \'tax_query\'      => array(
        array(
            \'taxonomy\' => \'topics\',
            \'operator\' => \'NOT EXISTS\',
            // missing the required \'terms\' parameter
        ),
    ),
) );
所以一定要使用tax_query 使用适当的参数。

您还可以使用/检查我的myloadmore.js script?

SO网友:Sally CJ

您的代码有几个问题,例如:

原文code 依靠全球$wp_query 对象请参见global $wp_query;misha_my_load_more_scripts() 作用但您的代码使用的是自定义WP_Query 实例,即$the_querymisha_loadmore_ajax_handler() 作用

misha_loadmore_ajax_handler() 是AJAX处理程序/回调,因此不应从div#main 像这样:

<div id="main" class="container-fluid">
  <?php misha_loadmore_ajax_handler(); ?>
</div><!-- END CONTAINER -->
因此原始代码可以工作;但是,对于自定义WP_Query 请求,如$the_query 在您的情况下,需要在WP_Query 要求

你可以这样做:

首先,我使用的是the page, 我正在使用“滚动加载帖子(延迟加载)”脚本/选项。

其次,这是我的misha_my_load_more_scripts() 功能:

function misha_my_load_more_scripts() {
    // register our main script but do not enqueue it yet
    wp_register_script( \'my_loadmore\', \'URL/to/the/load-more-script\', array(\'jquery\') );

    wp_enqueue_script( \'my_loadmore\' );
}
add_action( \'wp_enqueue_scripts\', \'misha_my_load_more_scripts\' );
和我的“main”div (邮政集装箱):

$current_page = max( 1, get_query_var( \'paged\' ) );
$the_query = new WP_Query([
    \'posts_per_page\' => 5,
    \'paged\'          => $current_page,
]);
?>
    <div id="main">
        <?php while ( $the_query->have_posts() ) : $the_query->the_post();
            // This should match the one in misha_loadmore_ajax_handler().
            get_template_part( \'template-parts/post/content\', get_post_format() );
        endwhile; ?>
    </div>
    <script>
        var misha_loadmore_params = {
            ajaxurl: \'<?php echo admin_url( \'admin-ajax.php\', \'relative\' ); ?>\',
            posts: \'<?php echo json_encode( $the_query->query_vars ); ?>\',
            current_page: <?php echo $current_page; ?>,
            max_page: <?php echo $the_query->max_num_pages; ?>
        };
    </script>
<?php
wp_reset_postdata();
这些是我所做的唯一改动misha_loadmore_ajax_handler() 代码(on that page) 可以按原样使用。

我已经尝试并测试了/我的代码,它正在按预期工作。虽然我没有使用您的代码,但我相信您可以使用您的代码/概念轻松实现我的代码。

如果要使用,请更新wp_localize_script() (尤其是如果您希望在JS对象/数据中包含翻译后的文本,可能会更好),那么您需要将load more脚本排入页脚:

wp_register_script( \'my_loadmore\', \'URL/to/the/load-more-script\', array(\'jquery\'),
  \'version\', true );
然后在“主要”div, 删除<script>...</script> 并将此添加到wp_reset_postdata():

wp_localize_script( \'my_loadmore\', \'misha_loadmore_params\', [
    \'ajaxurl\'      => admin_url( \'admin-ajax.php\', \'relative\' ),
    \'posts\'        => json_encode( $the_query->query_vars ),
    \'current_page\' => $current_page,
    \'max_page\'     => $the_query->max_num_pages,
    // These two are optional.
    \'my_text\'      => __( \'My text\', \'text-domain\' ),
    \'security\'     => wp_create_nonce( \'my-load-more-posts\' ),
] );
正如你所看到的,我在这里包括了一个翻译:My text (misha_loadmore_params.my_text).

Using a Nonce

在上面的本地化数据中,我还包含了一个nonce(security), 当您的AJAX PHP处理程序进行一些写操作时,这一点特别有用;e、 g.更新元数据。

您可以将其发送到PHP处理程序,如下所示:

// This is set in the load-more script.
var data = {
  \'action\': \'loadmore\',
  \'query\': misha_loadmore_params.posts,
  \'page\' : misha_loadmore_params.current_page,
  \'security\': misha_loadmore_params.security
};
然后在PHP处理程序中,您可以这样做来验证nonce:

function misha_loadmore_ajax_handler(){
    check_ajax_referer( \'my-load-more-posts\', \'security\' );

    ...
    wp_die();
}
PS:This 我加载的脚本是否更多,与原始脚本相比只有一个区别,即misha_loadmore_params.security 零件