【问题标题】:Laravel: how to render only one section of a template?Laravel:如何只渲染模板的一部分?
【发布时间】:2013-02-12 07:47:17
【问题描述】:

我正在尝试在我的网站上使用 pjax,这意味着对于整页请求,我会渲染整个模板(这是正常行为),但对于 pjax 请求,我只想渲染一个部分。我的模板都扩展了主模板。

我怎样才能最优雅地做到这一点?

【问题讨论】:

    标签: laravel laravel-4


    【解决方案1】:

    为什么不直接使用 div 或 html 元素替换呈现页面中的实际内容?

    我一直使用 jQuery 来做这件事。我只是构建我的初始页面并将内容发送到在我的主布局中呈现部分的视图。

    假设我有一个左侧导航栏,然后在右侧栏中有一篇文章。用户单击一个按钮以显示下一篇文章,这就是我要替换的内容。

    首先从你的控制器构建初始视图

    public function index()
    {  
      $article = Article::first();
      Return View::make('homepage', compact('article'));
    }
    

    现在在您的主页视图中

    @extends('layouts.master')
    
    @section('leftNavigation')
         @include('homepageLeftNavigation')
    @stop
    
    @section('article')
       <div id="articleContent">
         @include('article') <!-- see below, you'll update this include with the js below -->
       </div>
    @stop
    
    @section('script')
    @parent
    {{-- <script> --}}
    //in JQuery I would do something like this
    $('a.nextArticle').click(function(){
       var next = $('.nextArticle').attr("id");
       var next = next + 1;
       $('#articleContent').load({{ URL::to('articles/' + next ) }};
    });
    @stop
    

    假设您使用的是资源丰富的控制器,您可以使用 show() 函数,但如果您只想在主页上放一个预告片,您也可以轻松地为此创建一个新函数。

    在您的 show() 或 newFunctionWhateverYouCallIt() 中,您可以通过 id 获取文章

    Article::find($id);
    

    然后将其发送到要渲染的视图。

    return View::make('article');
    

    最后,您调用的文章视图包括您第一次构建页面时以及通过 Jquery 或 pjax 更新后再次生成的页面

         {{ $article->title }}
         {{ $article->body  }}
         {{ $article->date }}
         <a href="#" class="nextArticle" id="{{ $article->id }}">Next Article ></a>
    

    请注意,我没有测试过这段代码,所以我确信有一些错误,但您对更新页面单个部分的逻辑有了大致的了解。

    【讨论】:

      【解决方案2】:

      这是一个老问题,但我想提出另一个解决方案。

      假设您有一个名为 main.blade.php 的视图布局和另一个扩展 main 的视图,名为 page.blade.php em>

      main.blade.php

      <!DOCTYPE html>
      <html lang="en-GB">
      <head>
          <title>My Title</title>
      
          @section('head')
              <link rel="stylesheet" href="{{ URL::asset('css/style.css') }}">
          @show
      </head>
      <body>
      
          @yield('content')
      
          @section('footer')
              <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
              <script type="text/javascript" src="{{ URL::asset('js/main.js') }}"></script>
          @show
      </body>
      </html>
      

      page.blade.php

      @extends('main')
      
      @section('content')
          <div class="container">
              This is a rendered page
          </div>
      @stop
      

      只需一个简单的基本模板即可开始。在您的控制器中,如果您返回 View::make('page'),您将获得完整的 HTML,但 Laravel 提供了一种返回特定部分的方法。下面是一个示例,说明如何根据是否来自控制器内部的 ajax 调用来显示您想要的内容:

      my_controller.php

      function get_index() {
          $view = View::make('page');
      
          if(Request::ajax()) {
              $sections = $view->renderSections(); // returns an associative array of 'content', 'head' and 'footer'
      
              return $sections['content']; // this will only return whats in the content section
      
          }
      
          // just a regular request so return the whole view
      
          return $view;
      }
      

      现在,当您对页面进行 ajax 调用时,它只会返回内容部分而不是整个 HTML。

      【讨论】:

      • @Inigo 我只是再看一遍,并决定我之前的检查方式有点草率。所以编辑了请求部分。
      • @user151841 我在 Laravel 5.2.39 上测试了它,它仍然可以正常工作。我认为你不需要做任何不同的事情。
      【解决方案3】:

      在控制器的操作中,显式返回要渲染的局部视图:

      public function action_someajax()
      {
          ...
          return View::make('mypartial', $data);
      }
      

      这将呈现部分而不是控制器的布局。

      【讨论】:

      • 这将如何工作?这(几乎)是我现在使用它的方式:return View::make('page', $data); 和那个页面然后是@extends('master')
      • @duality_ 你必须在你的控制器中指定你的模板,而不是在你的每个视图中指定它才能工作。
      • 不行。模板扩展的设计是设计问题,而不是代码/控制器问题。因此这个决定应该在视图中做出。
      • 然而你说,“我的模板都扩展了一个主模板。”。
      • 没错。看看迈克的回答。
      【解决方案4】:

      我现在最好的答案是在您看来,如果请求不是通过 AJAX 调用,它只能扩展主模板(布局):

      @if(!Request::ajax())
          @extends('master.template')
      @endif
      

      但是,请注意,此解决方案可能不适合您的特定模板(我只能猜测)。您需要确保每个模板/视图仅包含不重复的内容,例如侧边栏等。例如,如果您有一个需要使用 pjax 更新的内容区域,那么您的视图应该只包含任何内容应该改。

      【讨论】:

      • 它并不完美,但非常接近。如果这可行(尚未尝试过)并且没有人提供更好的解决方案,我会接受这个答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-20
      • 2012-06-24
      • 1970-01-01
      相关资源
      最近更新 更多