【问题标题】:Change browser url without page reloading with ajax request更改浏览器 url 而无需使用 ajax 请求重新加载页面
【发布时间】:2014-05-07 15:07:37
【问题描述】:

所以我正在关注本教程:

http://www.tinywall.info/2012/02/change-browser-url-without-page-reload-refresh-with-ajax-request-using-javascript-html5-history-api-php-jquery-like-facebook-github-navigation-menu.html

我的目标是加载视图的实际内容并更改浏览器 URL 而无需重新加载页面。但是,因为我使用 CodeIgniter 作为我的应用程序的框架,所以我无法让它正常工作。我有一个控制器,我在其中加载所有仪表板的视图,我希望在名为 content_container 的 div 中显示这些视图。

问题是,每次我单击另一个锚标记以通过 ajax 请求加载不同的视图时,它都会在我的 url 中添加另一个“仪表板”,当然之后它不会显示视图。因此,单击几次后,URL 将如下所示:“dashboard/dashboard/dashboard/profile”。我尝试使用 Javascript 拆分 URL,但这对我没有帮助。

一种解决方案是为每个视图创建一个控制器,但我认为这是一种不好的做法,而且代码更简洁,只有一个控制器来处理所有视图。

这是控制器:

<?php

class Dashboard extends CI_Controller {

    public function __construct()
    {

        parent::__construct();
        $this->output->nocache();
        $this->load->model('subject_model');
        $this->load->model('user_model');
    }


    public function index()
    {

        $this->load->view('header');
        $this->load->view('dashboard');
        $this->load->view('footer');
    }

    public function users() 
    {

        $data['users'] = $this->user_model->getUsers();
        $this->load->view('staff_users', $data);
    }
    public function lomake()
    {

        $this->load->view('lomake');
    }

    public function profile()
    {

        $data['userinfo'] = $this->user_model->getUserInformationById($this->session->userdata('user_id'));
        $this->load->view('myprofile', $data);
    }

    public function subjects()
    {

        $this->load->view('subjects');
    }   
}
?>

这是我的仪表板视图(部分):

<aside id="left_control_panel">

    <ul id="left_control_links">
        <li>
        <a href="home" id="ajax" class="active">Home</a>
        </li>
        <li>
        <a href="dashboard/subjects" rel="tab">Subjects</a>
        <span class="list_total_count"><?=$total_subjects?></span>
        </li>

        <li>
        <a href="dashboard/lomake" id="ajax">Query</a>
        </li>

    <?php if($this->session->userdata('user_type') == 'admin'):?>

        <span class="left_control_heading">User management</span>
        <li>
        <a href="dashboard/users" rel="tab">Users</a>
        <span class="list_total_count"><?=$total_users?></span>
        </li>

        <li>
        <a class="add_user" href="add_user">Add User</a>
        </li>
    <?php endif;?>

        <span class="left_control_heading">Account management</span>
        <li>
        <a href="dashboard/profile" rel="tab">My Profile</a>
        </li>

        <li>
        <a href="<?=base_url()?>users/logout">Sign Out</a>
        </li>
    </ul>
</aside> <!-- end of left_control_panel -->

<div id="wrapper_loggedin">
        <div class="content_container">
        <! -- I will display all the data from different views in here -->
        </div>
</div> <!-- end of wrapper_loggedin -->

最后是 JS 部分,也可以在教程中找到:

$(function(){
    $("a[rel='tab']").click(function(e){
        //e.preventDefault(); 
        pageurl = $(this).attr('href');

        $.ajax({url:pageurl+'?rel=tab',success: function(data){
            $('.content_container').html(data);
        }});

        //to change the browser URL to 'pageurl'
        if(pageurl!=window.location){
            window.history.pushState({path:pageurl},'',pageurl);    
        }
        return false;  
    });
});

/* the below code is to override back button to get the ajax content without reload*/
$(window).bind('popstate', function() {
    $.ajax({url:location.pathname+'?rel=tab',success: function(data){
        $('.content_container').html(data);
    }});
});

Application/config/routes.php

$route['dashboard'] = 'dashboard/index';

$route['dashboard/(:any)'] = 'dashboard/$1';

【问题讨论】:

  • 有人可以帮我解决这个问题吗?

标签: javascript jquery ajax codeigniter url


【解决方案1】:

嗯,根据我的具体情况,我有成千上万的产品按类别和子类别组织。好吧..那是要写的大量 url 和控制器。所以我所做的是制作一个类别模板、一个子类别模板和一个产品页面模板。然后在我的 application/config/routes.php 文件中创建如下路由:

$route['products'] = 'products/index';

//so i know now they are on a category page and $1 is the name of the category.
//i can go query my db and get all subcategorys and the products under each now.
$route['products/(:any)'] = 'products/category/$1'; 

//the 1 and 2 here are category and subcategory from the url. so i know from this to
//use these in my query to grab all products in this category and subcategory.
$route['products/(:any)/(:any)'] = 'products/subcategory/$1/$2'; 

//i know this is gonna be a product page. and i know the category, the sub category and the product name. in this case all i really need is the product name since there is only one product with that name.
$route['products/(:any)/(:any)/(:any)'] = 'products/details/$1/$2/$3';

在您的情况下,您也可以这样做。使用您的网址,您花时间构建它们,所以使用它们。在 javascript 中,您可以通过“window.location.pathname”将它们发送回您的控制器;您所要做的就是将其拆分,您可以使用相同的心态来加载页面并确切知道您在哪里。

此外,在您的 ajax url 属性中,确保您的 url 是绝对 url,或者它首先引用根目录。我想我知道你的问题是什么。您在 url 属性中使用类似“users/dashboard”的 url,而它应该是“/users/dashboard”,您需要始终转到根目录并获取控制器,否则它会使用该 url 并始终采用“用户/仪表板”到您所在的当前网址。因此,如果您在“users/dashboard”上并再次加载它,您实际上是在告诉它加载“/users/dashboard/users/dashboard”,这将成为一个无限循环。只需在您的 url 前面加上一个反斜杠,它就会始终引用根目录。

【讨论】:

  • 所以在我的情况下,实际的模板是“仪表板”?我只是根据我按下的链接将数据附加到仪表板。
  • 是的,因为您的仪表板是需要处理所有页面的控制器,那么每个页面都应该由您的仪表板处理。因此所有 url 参数都将传递给它,您的控制器需要处理您设置的不同模板的所有参数。 like user_type == 1 加载此模板; user_type == 2 加载此模板等
  • 我还是不太明白。我编辑了我的 OP 以显示我是如何配置我的 routes.php 的。我应该在我的“仪表板”-控制器中更改什么?我应该如何引用我的链接? " 我需要在 javascript 文件中进行哪些更改?
  • 您需要记住,无论何时您使用控制器的方法并尝试链接回根控制器,您都必须使用绝对 URL。这就是 base_url() 函数可用的原因。因此,无论何时使用 achor 标签,请确保使用 base_url()/dashboard/users 等。否则,dashboard/users 只会将其附加到当前 url。
  • 我看到了您建议的编辑并尝试使用它们。似乎它现在以某种方式工作。但是仍然存在一些问题,一些 url 将在没有实际标题部分的情况下加载(不包括样式表)。
【解决方案2】:

我只是做了同样的事情。我这样做的方式是首先创建一条动态路由以始终指向同一个控制器。 $route['products/(:any)/(:any)/(:any)'] = 'products/details/$1/$2/$3';等等,那么只要您的页面通过 url 加载(如果有人输入特定的 url),您仍然会获得内容(书签仍然有效,您可以将特定的 url 发送给人们等)。然后我所做的是每个更改内容的链接也应用了一个数据属性来构建 url,我也将使用这些属性传递回同一个控制器。该控制器还检查请求是否来自 ajax 请求……如果是,您只需加载页面内容……如果不是,则加载完整模板。它真的没那么难,你几乎拥有我所拥有的。我觉得你想多了。但我要做的第一件事是确保首先访问带有 url 的每个页面。然后尝试让 ajax 部分工作。关键是检测请求是否来自 ajax 或不在控制器中。然后你就可以区分两者了。

【讨论】:

  • 你能给我一些你的代码示例吗?我不熟悉使用 CodeIgniter 设置路由。
【解决方案3】:

另外,我强烈建议您阅读用户指南。当您开始使用 Codeigniter 构建项目时,路线通常是您应该首先了解的内容之一。

http://ellislab.com/codeigniter/user-guide/general/routing.html

【讨论】:

    【解决方案4】:

    回答您关于核心控制器的问题。答案是肯定的,您在核心文件夹中创建了一个控制器。它必须有一个特定的名称。在您的 application/config/config.php 文件中,您应该有:

    $config['subclass_prefix'] = 'MY_';
    

    这定义了任何扩展核心控制器、模型或系统类的前缀。大多数 Codeigniter 系统类都可以扩展,您可以覆盖属性(变量)和方法(函数)。在您的情况下,您将在 application/core 文件夹中放置一个名为 MY_Controller.php 的文件。在这个控制器中,您可以像编写任何其他控制器一样使用它,这样您就不必一遍又一遍地重写相同的代码,或者更改默认控制器的操作方式。您应该阅读 php 类的工作原理以及使用它们的目的。 Codeigniter 并没有真正像您使用类的方式那样使用它们,但他们使用 MVC 方法来处理它。通常,类被称为对象。将班级想象成熊。熊有体重、年龄、长度、颜色、身高。所有这些都称为“属性”。熊也可以吃、喝和打猎。这些中的每一个都称为“方法”。更详细的熊是北极熊、恐怖熊或熊猫。这些可能是熊对象的子对象(它们将扩展熊对象)。任何子对象都继承其父属性和方法。但他们的价值观和行动可能会有所不同。北极熊的颜色、大小、身高与熊猫不同,但它仍然吃、喝、打猎。有些属性和方法可能不会改变,因此没有理由在子类中重写它们。因此,在您的情况下,核心控制器可以处理每个页面所做的事情。它可以验证会话、跟踪用户活动、定义全局错误消息等。我什至在我的核心控制器中创建了一个方法,将我的模板片段(页眉、页脚、侧边栏、内容)加载在一起,所以我没有当我加载我的模板时,必须继续堆叠 $this->load->view() 。我所要做的就是传递需要传递的内容和数据,并将我的模板加载到任何地方。您还需要了解 __construct 的工作原理。您可以将 __construct 视为始终在页面加载之前首先运行的函数。因此,通过在您的核心控制器中定义一个构造,您可以自动填写数据。浏览这些链接,深入了解如何使用这些功能并展示示例。

    http://ellislab.com/codeigniter/user-guide/general/core_classes.html

    http://www.php.net/manual/en/language.oop5.php

    如果这引导您朝着正确的方向前进,请给我投票 :) 我正在尝试建立我的积分和个人资料,并最终将我的帐户链接到我的网站,这样它就证明了我对任何未来的 php 和 codeigniter 知识过多员工。

    【讨论】:

      最近更新 更多