在不加载页面的情况下从“按类别排序帖子”菜单更改 <div> 内的内容

Posted

技术标签:

【中文标题】在不加载页面的情况下从“按类别排序帖子”菜单更改 <div> 内的内容【英文标题】:Change content inside <div> from "sort posts by category" menu without page load 【发布时间】:2016-07-22 15:04:18 【问题描述】:

我在这个网站上的第一篇文章,我正在为我的第一个自定义 wordpress 主题寻求一些指导。我对 jQuery/AJAX 非常陌生,此刻它伤害了我的大脑,因为整个过程一直是一个接一个的学习曲线。所以请原谅我无法看清字里行间并理解已经存在或可能已经存在的东西。当我搜索时,有一些关于这个主题的结果,但是我无法将这些示例转换为适合我的情况的工作结果......

我希望在“新闻”部分按类别对我显示的帖子进行排序...&lt;div id="#container"&gt; 中有一个子菜单...我的目的是让子菜单链接专门更改我的 @987654324 中的内容@...

即“最新消息”、“最近的构建项目”、“新闻稿”等......

这是来自“page-news.php”的一些代码和原始链接Cars & Coffee HFX

<div id="news_submenu_container"><!-- begin submenu placement -->
            <ul id="news_submenu">
              <li>VIEW</li>
              <li><a href="#" onClick="get_posts_all();">ALL</a></li>
              <li><a href="#" onClick="get_posts_news();">NEWS</a></li>
              <li><a href="#" onClick="get_posts_builds();">BUILDS</a></li>
              <li><a href="#" onClick="get_posts_pr();">PR</a></li>
            </ul>
        </div><!-- end submenu placement -->

        <script>
            function get_posts_all() 
                var posts_all_var = '<?php echo "Insert Wordpress Loop here identified by Category-ID" ?>';
            document.getElementById("contentbox-news").innerhtml = posts_all_var;
            return false;
            

            function get_posts_news() 
                var posts_news_var = '<?php echo "Huh?" ?>';
            document.getElementById("contentbox-news").innerHTML = posts_news_var;
            return false;
            

            function get_posts_builds() 
                var posts_builds_var = '<?php echo "Cant get loop to work" ?>';
            document.getElementById("contentbox-news").innerHTML = posts_builds_var;
            return false;
            

            function get_posts_pr() 
                var posts_pr_var = '<?php echo "DAMNIT!" ?>';
            document.getElementById("contentbox-news").innerHTML = posts_pr_var;
            return false;
            
        </script>

我现在明白 javascript 和 PHP 不能像我想象的那样一起工作...显然我需要通过 AJAX 使用一种方法...我在PHP AJAX and mysql 上找到了这篇文章但是它对我来说太高级了,我无法理解它并为自己创建一个工作示例......

但是现在,从昨天开始,我编写了新代码,让我走到了这一步,我可以 PHP 回显……就是这样。

            function get_posts_builds() 
                var posts_builds_var = '<?php query_posts('cat=6'); 
                                              while (have_posts()):
                                              the_post(); 
                                              the_content(); 
                                              endwhile; ?>';
            document.getElementById("contentbox-news").innerHTML = posts_builds_var;
            return false;
            

一旦我用这个 PHP wordpress 循环替换了 PHP 回显,它似乎对我不起作用并中断了。

【问题讨论】:

你只会在post-type-all.php中得到错误,你还没有加载wp,但是你为什么不使用ajax的wp方法呢?整体工作量减少! 有没有一种通过 wordpress 的方法可以让我通过菜单链接更改帖子循环而无需刷新页面? 您可以将内容加载到 JavaScript 变量中并使用 innerHTML 来填充 div - 使用使用 var content_var = &lt;?php $the_content ?&gt;document.getElementById('contentbox-news').innerHTML = content_var; 的函数在链接中构建 onclick() 事件 是的 google wpajax 但它是有代价的为您想要的帖子加载整个缓存页面 【参考方案1】:

您确实需要使用 AJAX 来实现这一点。 Wordpress have its own way to handle ajax request,您可以通过下面详述的几个步骤来使用它。我将尝试展示一些关于这个主题的 WP 最佳实践——因为可能有更快/更容易/更脏的方法来实现这一点(甚至可能通过插件),这将为您介绍 Wordpress 主题/插件开发。请随意点击文档链接以更好地了解其工作原理。


1。构建您的类别菜单

在您的代码示例中,菜单是静态的,但您最好使用动态菜单。一种解决方案是使用get_the_category_list,但它不允许您完全控制类别链接。我建议像这样定义一个新的navigation menu(以下代码进入您的主题functions.php):

add_action('after_setup_theme', 'add_categories_menu');
function add_categories_menu() 
  register_nav_menu('categories_menu', __('Categories Menu', 'your-theme-slug'));

然后在您的模板中,将您的静态菜单替换为以下内容以显示您的全新菜单:

<?php wp_nav_menu(array('theme_location' => 'categories_menu')); ?>

现在要将类别添加到您的菜单,登录您的 Wordpress 管理,进入 外观 > 菜单,创建一个新菜单,选择主题位置“类别菜单”,然后将类别添加到其中。

为此的最后一步,我们将添加a filter,以便在菜单链接上添加onclick 属性,将类别slug 发送到我们稍后定义的名为showPostsFromCategory() 的js 函数。

这进入你的functions.php

function add_onclick_attr_categories_menu($atts, $item, $args) 
    if($args->theme_location == 'categories_menu' && $item->object == 'category') 
        $category = get_category($item->object_id);
        if($category !== null) 
            $atts['onClick'] = 'showPostsFromCategory("' . $item->slug . '")';
        
    
    return $atts;

add_filter('nav_menu_link_attributes', 'add_onclick_attr_categories_menu', 10, 3);

您可能想问,为什么我们要在菜单项上保留类别链接? 这是为了 SEO 和可访问性目的:对于没有 javascript 的浏览器(如屏幕阅读器)或搜索爬虫,类别页面仍然可以访问。


2。为 AJAX 准备主题

在 Wordpress 中,所有 AJAX 请求都需要发送到 wp-admin/admin-ajax.php,并带有一个用于识别请求的操作参数,以便使用 wp_ajax_nopriv_my_actionfunctions.php 中捕获它(对于非登录用户)和wp_ajax_my_action(登录用户)钩子。

因此,在更进一步之前的一小步是使该路径 (wp-admin/admin-ajax.php) 在您的 JavaScript 中可访问。首先,在你的主题文件夹中创建一个我们将用于 AJAX 进程的 js 文件,假设他的名字是./js/categories-ajax.js。然后,在您的 functions.php 中添加以下内容,以便 enqueue 这个新脚本并使路径可以通过 script localization 访问:

add_action('wp_enqueue_scripts', 'ajax_categories_enqueue_scripts');
function ajax_categories_enqueue_scripts() 
    wp_register_script('categories_ajax', get_stylesheet_directory_uri() . '/js/categories-ajax.js', array('jquery'), '', true);
    wp_localize_script('categories_ajax', 'ls', array(
        'ajax_url'                  => admin_url('admin-ajax.php')
    ));
    wp_enqueue_script('categories_ajax');

有了这个 admin-ajax.php 路径将可以在你的 JS 中使用ls.ajax_url 访问。


3。触发ajax请求

是时候创建showPostsFromCategory() 函数了。所以让我们写在你的新 categories-ajax.js 文件中。就个人而言,为了避免在我的插件/主题开发中与 jQuery 发生任何可能的冲突,我喜欢总是将我的 jQuery 代码封装在 JavaScript closure 中,并让这些函数可以通过全局变量访问,如下所示:

(function($)
  showPostsFromCategory = function(category_slug) 
    // code function...
  ;
)(jQuery);
var showPostsFromCategory;

所以我现在假设函数代码在闭包内。 基本上,我们现在需要做的是向 admin-ajax.php 设置一个$.post 请求,该请求将发送以下参数:

action:正在调用的 AJAX 操作的标识符,以便让 Wordpress 知道以后应该调用哪个函数。我们将其命名为dynamic_categoriescategory: 菜单中被点击的分类slug。

所以函数代码会是这样的:

showPostsFromCategory = function(category_slug) 
    $.post(ls.ajax_url, action: 'dynamic_categories', category: category_slug, function success(data) 
        $('#your-post-content-wrapper').html(data); // Update the page with the new posts -- change this ID to the correct one
    );
    return false; // this is to cancel the link click, so the page isn't being redirected

这是非常基本的,您可能希望稍后添加一些错误处理和加载器。在这里,我们只是用 AJAX 返回替换实际的帖子,我们假设它是 HTML。 JS 端没什么可做的,现在让我们在 PHP 端工作吧。


4。获取请求类别的帖子

首先,在您的 functions.php 中添加以下行,以便将函数 get_categories_posts() 附加到 wp_ajax_dynamic_categorieswp_ajax_nopriv_dynamic_categories 操作。

add_action('wp_ajax_dynamic_categories', 'get_categories_posts');
add_action('wp_ajax_nopriv_dynamic_categories', 'get_categories_posts');

现在,我们需要在函数中执行以下操作:

    检查类别 slug 是否有效以及是否关联了帖子,否则显示错误。

    Get the posts 与由 JS 脚本发送的 slug 标识的类别相关联。

    循环浏览帖子并使用template part 显示每个帖子。为此,请在您的主题文件夹中创建一个模板,该模板将仅包含显示 一个 帖子所需的 HTML/PHP。您可以在 template-parts/content.php 的默认 wordpress 主题 (twentysixteen) 中看到此类模板的示例。在您的主题中执行相同类型的文件 - 也许已经有一个。您将需要更新您的存档模板以使用模板部分。这很简单,删除用于显示帖子的代码inside循环并替换为:

     <?php get_template_part('template-parts/content'); ?>
    

所以整个函数代码会是这样的:

function get_categories_posts() 
    // Check if the category slug provided is ok and if it have posts
    if(!isset($_POST['category'])) 
        die('<p class="error">' . __('No category parameter provided', 'your-theme-slug') . '</p>');
    
    $category_slug = sanitize_text_field($_POST['category']);
    $category = get_category_by_slug($category_slug);
    if(!$category) 
        die('<p class="error">' . sprintf(__('Category %s not found', 'your-theme-slug'), $category_slug) . '</p>');
    
    $posts = get_posts(array(
        'category' => $category->term_id,
        'posts_per_page' => -1 // get all posts
    ));
    if(empty($posts)) 
        die('<p class="error">' . sprintf(__('The category %s is empty', 'your-theme-slug'), $category->name) . '</p>');
    
    
    // Loop through the posts and display them
    foreach ($posts as $post) 
        setup_postdata($post);
        get_template_part('template-parts/content');
    
    die('');

而且,仅此而已!有了这个,您现在可以为您的帖子类别提供动态导航。

供参考:sanitize_text_fieldget_category_by_slugget_postssetup_postdataget_template_part


请注意,这不支持分页。如果您需要这个,请查看this answer我提出的这件事。


进一步阅读

How to use AJAX in Wordpress Understanding get_template_part

【讨论】:

Vard,感谢您的帮助。我已按照这些说明进行操作,但我无法理解如何指向链接以将帖子显示为某个 div 容器内的循环,称为 #contentbox-news... 你是说在模板部分里面?您可以通过get_permalink()获取当前帖子的链接

以上是关于在不加载页面的情况下从“按类别排序帖子”菜单更改 <div> 内的内容的主要内容,如果未能解决你的问题,请参考以下文章

如何在不更改顺序的情况下从 plist 加载数据

为啥 Python 3.8.0 允许在不使用“非本地”变量的情况下从封闭函数范围更改可变类型?

如何在不更改代码的情况下从已编译的 jar 中检索完整的异常消息?

如何在不刷新网页的情况下从下拉列表索引更改事件的数据库中检索数据

如何在不重新加载页面的情况下更改页面 url

如何在不与 MainActivity 交互的情况下从通知中打开片段页面?