如何保持元素不刷新

27

主要目标是保持logo文本<div class="small-7 medium-4 columns logo">和菜单<nav class="pagedMenu" role="navigation">在页面刷新或从一个页面加载内容到另一个页面时不被剪辑,同时还应该从一个页面到另一个页面保留菜单状态。

我在这里找到了一个可能解决问题的方法(@jfriend00说:你可以使用ajax获取更新后的内容,并使用jQuery将新内容放置在页面上,完全避免刷新。那样做,页面中现有的数据将保持不变。

因此,我尝试使用一个Ajax插件(名为AWS)。在AWS选项页面中,我(假设)已经正确地将wrapper指向Ajax container ID,并且将pagedMenu指向Menu container class,启用Transition EffectNo ajax container IDs为空,没有选择加载器,因为主题中已经实现了pulse loader。

到这一步,我得到的只是一个菜单/侧边菜单(shiftnav)/ pulse dot loader / 内容加载故障,可能是由于错误定义的Ajax container id和/或menu container class(?)或与现有的JS/jQuery代码冲突,不太确定。

此外,在Chrome控制台中存在一个错误:

Uncaught SyntaxError: Unexpected token ;
(anonymous function) @ ajaxify.js?ver=4.3.1:175
n.extend.each @ jquery-2.1.4.min.js?ver=2.1.4:2
n.fn.n.each @ jquery-2.1.4.min.js?ver=2.1.4:2
$.bind.$.ajax.success @ ajaxify.js?ver=4.3.1:169
n.Callbacks.j @ jquery-2.1.4.min.js?ver=2.1.4:2
n.Callbacks.k.fireWith @ jquery-2.1.4.min.js?ver=2.1.4:2
x @ jquery-2.1.4.min.js?ver=2.1.4:4
n.ajaxTransport.k.cors.a.crossDomain.send.b @ jquery-2.1.4.min.js?ver=2.1.4:4

刷新页面后一切都恢复正常,但这完全没有帮助,毫无用处。

我还必须提到,在菜单方面,我尝试使用jQuery-Storage-API和storage=jQuery.sessionStorage;来保持状态,就像您在mynewmenu.js文件中看到的那样,但这并不能解决非刷新元素的问题。

如果需要整体情况,请查看此处提供的菜单jsfiddle,感谢@Diego Betto

您可以使用此实时链接作为示例;与上述描述类似 - Ajax实现正确吗 - 在外观方面,菜单从一个页面保持不刷新到另一个页面; 如果有可能实现的模型,我很高兴找到它。

LE: 同时,我尝试了由@arvgta制作的另一个ajaxify解决方案 - 特别感谢 - 但尚未成功,但据我了解从作者那里发现,应定义元素具有id而不是类。因此,我将尝试找到一种方式来修改代码,以便具有id而不是类。

此外,我将尝试在ajaxify.min.js文件中转换和实施page-container元素; jQuery('#page-container').ajaxify(); 我会回来报告新闻。

LE2:我尝试使用id而不是类来实现解决方案,但仍然无法正确加载页面。

此时,我们已经更新了ajax.min.js文件,并添加了这些行:

(function($){

  jQuery(document).ready(function(){
    jQuery('#page-container').ajaxify({requestDelay:400,forms:false});
  });

})(jQuery); 

此外,我已修改主题文件将class=page-container更改为id=page-container

在这些条件下,当菜单被点击时,链接会发生变化(应该是这样的),菜单/标志文本元素似乎工作得几乎正常(有时会在位置变化时变得卡顿),但在所有情况下都无法正确加载内容; 在手动刷新页面(F5)后,一切都恢复正常,但没有帮助。

LE3:看起来冲突至少在 Revolution Slider 插件和 Ajaxify 之间。

errormessage="Revolution Slider 错误:您包含了一些 jquery.js 库,它在 revolution 文件 js include 之后。"
这包括消除了 revolution slider 库,并使其无法工作。"<span="">"

网站实时链接 here。任何想法/在这个领域的替代方案?(不想使用其他不同的平台、不同的 WordPress 主题等,只是在现有情况下找到一个解决方法)

LE4:据我所见,有很多用户投票支持 Jake Bown 的答案,可能确实是一个解决方案;但我找不到没有错误地实施到我的主题中的原因(此处有实时链接),标志文本/菜单元素仍然在刷新时淡出,不能保持不刷新。@Jake Bown / 任何人有什么想法吗?

LE 最终。 Buzinas 提供了最接近我需求的答案,考虑到我的站点环境(已安装的插件等)。


@typo_78,我建议你从一开始就用正确的方式。使用Backbone、Angular、Ember甚至React.js。 - IonDen
2
ajaxify试图将从通过ajax加载的请求页面中提取的脚本附加到DOM中(第175行),但某些脚本会变得损坏(&变成& amp;等),因此会出现语法错误。如果您不想按“正确的方式”操作,为什么不直接联系插件的作者寻求建议呢? - borisdiakur
1
是的,我指的是 ajaxify.js 中的第175行,插件通过 contentNode.appendChild(scriptNode); 添加脚本。而“正确的方式”是指IonDen的评论。尽管CBroe可能是对的,确实有一些不错的单页主题值得一试,可以从中获得一些灵感。 - borisdiakur
1
我认为(根据查看您的源代码)正在发生的事情是,您的菜单正在将内容加载到#wrapper中,但是您的菜单在#包装器内部,因此它也正在重新加载。尝试将菜单放在#wrapper之外,看看那会带给您什么结果。 - Patrick Lyver
1
您可以使用iframe实现此目的。只需将主文档仅包含图标或其他内容,并将所有内容放在iframe中即可。 如果您想让我编写一些代码,请告诉我。 我无法进行任何演示,因为iframes仅适用于相同域,并且jsfiddle和其他网站不允许iframes(就我所知)。 - www139
显示剩余22条评论
3个回答

6

根据您所说的,我想我可能已经找到了您正在寻找的解决方案 - 您想要动态加载内容同时保持标志和导航不变吗?如果是这样,这可能就是您要找的

在这个示例中,页面是从页面中的一个div中加载的,但也可以用于加载另一个URL或文件:

$('.viewport ul li a').on('click', function(e) {
   e.preventDefault();
   var link = this.hash.substring(1, this.hash.length);
   if($('.'+link).length) {
     $('.viewport span.body').html($('.'+link).html());
   }
});

谢谢您的回答,这可能是一个不错的解决方案,但我看不出如何应用到我的菜单上。就我们所见,我的菜单已经实现了一个jQuery序列,可以将状态从一个页面保持到另一个页面... 我该如何将它与您的解决方案结合起来呢?您能否请使用此jsfiddle作为基础进行操作(http://jsfiddle.net/ex3ntia/hrt2s221/7/)?非常感谢。 - typo_
1
你需要从另一个页面或当前页面内部加载数据吗?这是已实现到你的代码中的代码 http://codepen.io/jakebown/pen/WQoaPX - Jake Bown
谢谢您,每个页面都有自己的内容;您的代码将在当前页面加载内容吗? - typo_
抱歉,我现在很困惑 :) 那么,我该如何使用它,使每个页面都有自己的内容,并从页面底部删除那些行或... (?!) - typo_
这个版本获取URL的内容,由于跨浏览器限制,它在Codepen中无法工作,但您可以将http://www.stackoverflow.com URL替换为您自己网站上的页面,那样就可以工作了。codepen链接。 - Jake Bown
显示剩余5条评论

5

TL;DR

我已为你创建了一个 Plunker,可以看看并尽可能多地测试。你会从中学到很多东西!


其中,created a plunker for youplay with it as long as you can两个链接需要保留不变。

我认为你在这里尝试了太多的事情,但是没有尝试最简单的方法:

主要目标是保持标志文本和菜单的非刷新状态,在页面刷新或内容从一个页面加载到另一个页面时不会被裁剪。此外,菜单状态应该从一个页面保留到另一个页面。

如果您想做到这一点,有几个步骤:

  • Create a 'master' page, that we're going to call index.html from now on.
  • So, our index must have the static part of our page, e.g menu, logo, footer etc.
  • Then, our 'subpages' must be cut down (no html, head, body, script, style tags, only the content that should be showed into our master page).
  • That done, now we must change our links to use AJAX instead of doing full refresh:

    /* we add a 'click' event handler to our menu */
    document.getElementById('menu-menu-2').addEventListener('click', function(e) {
      var el = e.target;
    
      /* then, we see if the element that was clicked is a anchor */
      if (el.tagName === 'A') {
        /* we prevent the default functionality of the anchor (i.e redirect to the page) */
        e.preventDefault();
        /* we show our spinner, so the user can see that something is loading */
        spinner.classList.remove('hidden');
    
        /* and we call our AJAX function, passing a function as the callback */
        ajax(el.href, function(xhr) {
          /* we get our main div, and we replace its HTML to the response that came
             from the AJAX request */
          document.getElementById('main').innerHTML = xhr.responseText;
          /* since the request was finished, we hide our spinner again */
          spinner.classList.add('hidden');
        });
      }
    });
    
  • Ok, now our pages are already working via AJAX, and not reloading our static content.


但是现在我们发现存在一些问题。例如,如果有人尝试通过URL直接打开我们的页面,他将看到未经样式处理的页面,没有菜单/标志等。那么我们该怎么办呢?
现在我们需要进行几个步骤:
  • Simulate that our links are effectively transfering between pages using the History API:

    /* inside our ajax callback, we save the fake-redirect we made into the pushState */
    ajax(el.href, function(xhr) {
      document.getElementById('main').innerHTML = xhr.responseText;
    
      /* save the new html, so when the user uses the back button, we can load it again */
      history.pushState({
        html: main.innerHTML,
        title: el.textContent + '| neuegrid'
      }, '', el.href);
    
      /* (...) */
    });
    
    /* and outside it, we add a 'popstate' event handler */
    window.addEventListener('popstate', function(e) {
      /* so, if we've saved the state before, we can restore it now */
      if (e.state) {
        document.getElementById('main').innerHTML = e.state.html;
        document.title = e.state.title;
      }
    });
    
  • And we need that when the user enters directly to another page, e.g about-us, we redirect him to the index.html, and then load the about-us page from there.

  • So we create a redirect.js file, and we reference it in all of our subpages:

    /* save the page that the user tried to load into the sessionStorage */
    sessionStorage.setItem('page', location.pathname);
    /* and them, we redirect him to our main page */
    location.replace('/');
    
  • And then, in our index.html page, we see if there is any page in the sessionStorage, and we load it, if there is, otherwise we load our home page.

    var page = sessionStorage.getItem('page') || 'home';
    /* we look into the menu items, and find which has an href attribute 
       ending with the page's URL we wanna load */
    document.querySelector('#menu-menu-2 > li > a[href$="' + page + '"').click();
    

就这样,我们现在完成了。看看我为你制作的plunker

尽可能地玩耍它,这样你会从中学到很多东西。

希望能对你有所帮助! :)


注意:仅供参考,这是我们的 ajax 函数:
function ajax(url, callback, method, params) {
  if (!method) method = 'GET';

  var xhr = new XMLHttpRequest();
  xhr.open(method, url);

  if (callback) xhr.addEventListener('load', function() {
    callback.call(this, xhr);
  });

  if (params) {
    params = Object.keys(params).map(function(key) {
      return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
    }).join('&');
    xhr.send(params);
  } else {
    xhr.send();
  }
}

@typo_78,菜单是动态的对于这个解决方案没有任何影响。你在这里面遇到了什么问题? - Buzinas
据我所见,您上面的模型看起来像是一个闪屏页面的方法,对吗?问题在于我不知道如何将动态菜单链接先实现到静态页面中 :) - typo_
@typo_78 你怎么在动态的中实现它们? ;) - Buzinas
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/91241/discussion-between-typo-78-and-buzinas。 - typo_
正在进行中,但已经非常接近预期结果。感谢@Buzinas的帮助,我会及时回来更新消息。 - typo_
显示剩余3条评论

2

使用WordPress进行AJAX化

按照以下简单步骤操作(以WP模板文件夹中的主题"twentyfifteen"为例):

  1. 编辑single.phppage.phpindex.php和所有其他具有get_header()get_footer()函数的页面,并将其分别替换为下面的代码:

注意:这很重要,因为如果有人(例如搜索引擎)直接从链接访问您的页面,则仍然完全可用并且100%工作。(对于SEO很有用)


<?php 
//get_header()
if(!isset($_REQUEST['ajax'])){
  get_header();
}
?>

<!-- other code --->

<?php
//get_footer()
if(!isset($_REQUEST['ajax'])){
  get_footer();
}
?>
  1. 打开header.php文件,在<head>标签后面的最后添加以下代码
    <script>
!(function($) {
    $(function() {
        $('.menu-item a, .widget-area a, .page_item a').on('click', function(e) {
            e.preventDefault();
            var href = this.href;
            var query = href ? (href + (!/\?/g.test(href) ? '?' : '&') + 'ajax=1') : window.location;

            /* IMPLEMENT SOME LOGIG HERE BEFORE PAGE LOAD */
            /* ex: kill instance of running plugins */

            $('#content').hide().empty().load(query, function() {

                /* IMPLEMENT SOME LOGIG HERE AFTER PAGE IS LOADED */
                /* ex: refresh or run a new plugin instance for this page */

                jQuery(this).show();
            });
        });
    });
})(jQuery);
    </script>

header.php文件中,在文件结尾处放置下面的代码,大部分情况下,您需要在导航下方使用它。在这种情况下,我们已经在"twentyfifteen"主题上完成了此操作。

注意:很可能您已经在header.php文件中有开放标签<div id="content" class="site-content">,并且在footer.php文件中有闭合标签</div>,这没关系,您可以按照原样保留。

<div id="content"></div>
  • 注意:将此视为概念验证;它可能可以直接使用,但您仍然需要根据自己的需求进行定制;您可能需要:

    1. 通过转至 外观 > 菜单 > [检查主菜单] > 保存菜单 添加一个菜单(如果没有设置),以便激活菜单。已经测试过并且正常工作。
    2. 您可能需要向 jQuery 函数添加其他类,例如 .widget-area a,以使 ajax 也适用于小部件链接。
    3. 如果您正在使用第三方插件,则可能需要确保每个插件的所有依赖项都在从中显示所有内容而无需刷新内容的主页面上加载
    4. 在新页面加载之前,您可能需要检查和关闭那些第三方插件,并在加载的页面中运行刷新所需的插件。

简而言之:主要目标是在刷新页面时保持这两个元素不刷新(logotext和菜单),而其他内容正在加载中,使用脉动加载器等相同的结构。因此,我已根据您上述描述编辑了_page.php_和_single.php_(步骤1),在js文件中用page-container替换#ajax-content,但是对于帖子,我没有任何id,只有类(步骤2)...您认为我该如何继续?链接在这里 谢谢 - typo_
很遗憾,同样的故事。无论如何,感谢您的回答和关注。 - typo_
@typo_78:让我们在聊天中继续这个讨论... http://chat.stackoverflow.com/rooms/91409/going-ajaxed-with-wordpress - Luca Filosofi
我明白了,我找到了你3天前发布的帖子 :) 我想我们必须等待下一个更新版本(?) 如果你仍然想分享并提出答案,我很乐意找到它。不管怎样,这很奇怪,因为在Visual Composer中,在ajax环境中,视差元素的行为也是相同的,而且有缺陷(?!). - typo_
Visual Composer不是问题,Rev Slider就不同了,因为当您加载带有Slider的新页面时,您需要终止先前正在运行的Slider,然而,终止函数存在错误! - Luca Filosofi
显示剩余19条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接