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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15096241/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 02:23:39  来源:igfitidea点击:

Laravel: how to render only one section of a template?

laravellaravel-4

提问by duality_

I'm trying to use pjax on my site, which means that for a full page request I render the whole template (this is normal behaviour), but on pjax requests I would like to render just one section. My templates all extend a master template.

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

How can I most elegantly do that?

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

回答by JoeMoe1984

This is kind of an old question but I would like to throw down another solution.

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

Lets say you have a view layout called main.blade.phpand another view that extends main called page.blade.php

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

main.blade.php

主刀片.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

页面.blade.php

@extends('main')

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

Just a simple basic template to get things started. In your controller if you return a View::make('page')you will get the complete HTML but Laravel provides a way to return specific sections. Here is an example of how to display the content you want based on if its an ajax call or not from within your controller:

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

my_controller.php

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;
}

Now when you make an ajax call to the page it will only return the content section rather than the entire HTML.

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

回答by Joshua

Why wouldn't you just replace the actual content in the rendered page using a div or html element?

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

I do this all the time with jQuery. I simply build my initial page and send content to my views that render sections in my master layout.

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

Let's say I had a left navigation column and then an article in the right column. The user clicks a button to display the next article, so that's what I want to replace.

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

First build the initial view from your controller

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

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

Now in your homepage view

现在在您的主页视图中

@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

Assuming you're using a resourceful controller you could use your show() function, but if you just wanted a teaser on the homepage you could easily create a new function for that as well.

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

In your show() or newFunctionWhateverYouCallIt() you can just get the article by id

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

Article::find($id);

Then send that off to a view to be rendered.

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

return View::make('article');

And finally the article view you called included the when you first built the page and again after updating via Jquery or pjax

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

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

Please note I haven't tested this code so I'm sure there are a few mistakes, but you get the general idea of the logic for updating a single section of your page.

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

回答by Mike Rockétt

My best answer right now would be to state in your view that it must only extend the master template (layout) if the request is not being called via AJAX:

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

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

Note, however, that this solution may not be best for your specific templates (I can only guess that). You'd need to make sure that each template/view only contains things that do not repeat, like side bars, etc. For example, if you have a content area that needs to be updated with pjax, then your view should only contain whatever should be changed.

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

回答by Jürgen Paul

Inside your controller's action, explicitly return the partial view you wanted to render:

在您的控制器操作中,明确返回您想要呈现的部分视图:

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

This would render the partial instead of the controller's layout.

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