点击即可动态切换模板

时间:2013-09-20 作者:TechyDude

我有一个自定义的帖子类型设置和几个自定义字段。我正在创建一个显示所有自定义帖子类型的页面,但我希望有多个视图。请参见下面的示例。一个是列表视图,另一个是带有图像的平铺项目视图。

顶部将有按钮在模板之间切换。有没有一种方法可以在页面模板之间动态切换?我从来没有做过这样的事情,如果能在这件事上得到任何帮助,我将不胜感激!我宁愿不要让投资组合的每个视图都是一个新的页面。

谢谢enter image description here

enter image description here

3 个回复
最合适的回答,由SO网友:gmazzap 整理而成

我的答案有点像@allenericr 回答点+一些缓存。

我建议仅当这3个模板在内容上不同,而不仅仅是在方面不同时,才实现这一点,否则CSS+JS解决方案应该是最佳选择。

创建主页模板\'multi-template-page.php\' 仅包含开关按钮和get_template_part 调用以包括3个不同模板文件(名为。my-template-1.php, my-template-2.phpmy-template-3.php) 您必须为每个模板编写。

在主模板中输入如下内容:

<?php
/*
Template Name: Multi Template Page
*/

get_header(); ?>

<ul id="template_switches">
  <li><a href="#template-1" data-template="1" class="active">Template 1</a></li>
  <li><a href="#template-2" data-template="2">Template 2</a></li>
  <li><a href="#template-2" data-template="3">Template 3</a></li>
</ul>
<div id="template-target"><?php get_template_part(\'my-template\', \'1\'); ?></div>

<?php get_footer(); ?>
因此,默认情况下,您将激活并显示第一个模板。

然后,在functions.php 将此模板的脚本排入队列:

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

function template_switch_script() {
  if ( is_page_template(\'multi-template-page.php\') ) {
    wp_enqueue_script(\'multi-template\', get_template_directory_uri() . \'/js/multi-template.js\', array(\'jquery\'));
    $data = array(
       \'url\' => admin_url(\'admin-ajax.php\'),
       \'id\' => get_queried_object()->ID
    );
    wp_localize_script(\'multi-template\', \'multiTemplateData\', $data );
  }
}
现在必须创建jsvascript文件multi-template.js 在主题的js子文件夹中:

window.multiTemplateCache = {} // prepare a cache object

jQuery().ready( function($) {

  // cache the 1st template on load
  window.multiTemplateCache.template_1 = $(\'#template-target\').html();

  $(\'#template_switches li a\').click( function(e) {
    e.preventDefault();
    if ( $(this).hasClass(\'active\') ) return false; // do nothing if click active link

    var template = $(this).data(\'template\');

    if ( window.multiTemplateCache[\'template_\' + template ] ) { // look in cache

       // in cache, just output to page
       $(\'#template-target\').html( window.multiTemplateCache[\'template_\' + template] );

    } else { // not in cache, retrieve via ajax

      // remove current template and put a loading message
      $(\'#template-target\').html( \'loading...\' ); 

      // css stuff
      $(\'#template_switches li a\').removeClass(\'active\');
      $(this).addClass(\'active\');

      $.get(
        multiTemplateData.url,
        {
          postId: multiTemplateData.id,
          action: \'multi_template_template\',
          which: template
        },
        function( data ) {
          // cache the template
          window.multiTemplateCache[\'template_\' + template ] = data;
          // output the template to page
          $(\'#template-target\').html( data );
        }
      );

    } // end if

  }); // end on click event

}); // on ready event
此脚本单击其中一个开关链接,检查缓存对象中是否已加载模板,如果已加载,则将其输出。如果没有,则发送一个通过所需模板的ajax请求。

在将内容放入页面之前,它会被缓存,因此每个模板都会触发一次ajax调用。但仅适用于模板2和3,因为加载时缓存了模板1:)

那么,现在在你的function.php 您必须添加ajax操作和相关函数。

add_action(\'wp_ajax_multi_template_template\', \'multi_template_template\');
add_action(\'wp_ajax_nopriv_multi_template_template\', \'multi_template_template\');

function multi_template_template() {
  $template = isset($_REQUEST[\'which\']) ? $_REQUEST[\'which\'] : false;
  if ( ! $template ) die(\'Sorry, impossible to load content\');
  $postid = isset($_REQUEST[\'postId\']) ? $_REQUEST[\'postId\'] : false;
  if ( $postid ) {
    global $post; // I\'m setting global $post just-in-case the template make use of it
    $post = get_post($postid);
  }
  get_template_part(\'my-template\', $template);
  die();
}
您可以改进我的代码,添加# 功能,即当您指向以下地址时http://example.com/multi-template-page/#template2 模板2被设置为活动的,并为第一个加载。。。

SO网友:Milo

您可以通过rewrite endpoint. 这将为每次单击按钮向服务器发送一个请求,您必须自己格式化链接以将端点附加到永久链接,不确定这是否满足您的要求。

首先注册page post类型的端点:

function wpa_view_endpoint(){
    add_rewrite_endpoint( \'view\', EP_PAGES );
}
add_action( \'init\', \'wpa_view_endpoint\' );
现在,对于每个页面,如:

http://example.com/some-page/
您还可以有如下URL:

http://example.com/some-page/view/list/
的价值view 将通过以下方式在您的模板中提供get_query_var:

$view = get_query_var( \'view\' );
然后可以显示基于该值的任何标记。

您还可以过滤页面模板的加载,并通过以下方式为每个视图加载单独的模板:

function wpa_view_template( $template = \'\' ){
    global $wp_query;
    if( isset( $wp_query->query_vars[\'view\'] ) ) {
        $template = locate_template( $wp_query->query_vars[\'view\'] . \'.php\', false );
    }
    return $template;
}
add_filter( \'page_template\', \'wpa_view_template\' );
例如:

http://example.com/some-page/view/list/
此筛选器将加载模板list.php 而不是默认的页面模板。

SO网友:Eric Allen

如果您只是想避免页面加载,那么可以通过多种方式来实现。我在下面列出了其中的一些。

然而,首先你应该问问自己,是否真的需要避免页面加载,是否值得为此付出额外的努力,模板之间是否会有某种平滑的过渡,或者只是突然交换,你将如何处理这种过渡,等等?

以下是我可以想到的各种选择(可能还有许多其他可能的解决方案):

已经为各种视图加载了CSS,然后在按钮上应用一个类,单击该按钮可以更改CSS中的布局,并将视图数据存储为data- 单击按钮上的原始视图属性和加载视图数据使用ajax将具有指定视图的页面模板加载到页面内容中,使用jQuery的.load() 方法,您可以指定要加载页面的哪些部分,以便只替换<div id="content"> 内容为<div id="content"> (或者无论您的内容节将要更改的内容是什么)从另一个url

  • 在JS模板系统中构建模板,并在单击时触发模板更改,将帖子信息作为脚本标记中的JSON对象添加到页面,然后在加载时可以构建和填充默认模板,在单击按钮时可以构建和填充所选模板设置一个WordPress ajax操作,您可以向其发送模板段塞,它将调用get_template_part(\'content\', $slug); 然后你可以将这些内容注入到你的页面中,只需为点击按钮时要加载的模板发送一个slug,将所有不同的模板HTML加载到页面上,然后只需在点击按钮时显示和隐藏模板,我不知道这些解决方案是否完美,但我想说的是1和3或6的某种组合将是我的选择。我想在大多数情况下,我更喜欢3而不是6,这样我就有了实际存在的页面。

    如果模板在内容和布局上没有太大的不同,我会说只使用CSS类来重新配置它,但是从上面的图片来看,模板的性质似乎会非常不同,如果你只使用没有JS的CSS版本,你将隐藏和显示图像,而不知道用户是否想看到它们,无缘无故浪费了一些带宽。

    我可能会为每个视图设置一个页面,告诉它使用哪个模板,然后当用户单击按钮时,我会从另一个模板中提取内容,然后将其插入当前模板的内容所在的位置。

    这样,爬虫程序(无需设置HTML快照)和浏览器因任何原因缺少JS/AJAX的用户就可以使用其他视图。

    您还可以从WordPress安装和加载保存的HTML中设置的任何缓存中获益。

    而且,如果有人想在推特或Facebook帖子中链接到一个视图,其他单击他们链接的人将被带到该视图,但也可以查看其他视图。

    我会让模板按钮链接到这些页面,然后使用e.preventDefault() 在模板按钮锚定标记的click event listener上。

    您还可以钩住历史API,将新状态注入浏览器的历史。这样,用户可以在切换模板时使用后退/前进按钮。

    您也可以连接历史API,而不需要单独的页面,只需通过历史API中可用的方法更改所有内容,但是如果您的模板以页面的形式存在,那么您就不必处理通过HTML快照和哈希片段使其他模板状态可爬行的头痛问题。(不过,我从未将历史API挂接到我注入的状态也作为独立URL存在于我的网站上的页面上,因此可能会产生一些复杂情况)

  • 结束