Laravel:如何只渲染模板的一个部分?

dua*_*ty_ 17 laravel laravel-4

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

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

Joe*_*984 41

这是一个老问题,但我想抛弃另一个解决方案.

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

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>
Run Code Online (Sandbox Code Playgroud)

page.blade.php

@extends('main')

@section('content')
    <div class="container">
        This is a rendered page
    </div>
@stop
Run Code Online (Sandbox Code Playgroud)

只是一个简单的基本模板来开始.在您的控制器中,如果您返回a,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;
}
Run Code Online (Sandbox Code Playgroud)

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


Jos*_*hua 10

为什么不使用div或html元素替换渲染页面中的实际内容?

我一直用jQuery做这个.我只是构建我的初始页面并将内容发送到我的视图,这些视图在我的主布局中呈现部分.

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

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

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

现在在您的主页视图中

@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
Run Code Online (Sandbox Code Playgroud)

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

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

Article::find($id);
Run Code Online (Sandbox Code Playgroud)

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

return View::make('article');
Run Code Online (Sandbox Code Playgroud)

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

     {{ $article->title }}
     {{ $article->body  }}
     {{ $article->date }}
     <a href="#" class="nextArticle" id="{{ $article->id }}">Next Article ></a>
Run Code Online (Sandbox Code Playgroud)

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


Mik*_*étt 5

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

@if(!Request::ajax())
    @extends('master.template')
@endif
Run Code Online (Sandbox Code Playgroud)

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