Включая JavaScript внизу страницы, из частичных представлений - PullRequest
10 голосов
/ 18 ноября 2011

Допустим, у меня есть слайд-шоу JavaScript в частичном представлении ...

_Slideshow.cshtml:

@{
    ViewBag.Title = "Slide Show";
}
<div id="slides">
</div>
<script src="js/slides.min.jquery.js"></script>
<script type="text/javascript">
$(function(){
    $('#slides').slides({
        // slide show configuration...
    });
});
</script>

Но я хочу быть хорошим маленьким веб-разработчиком и следить за тем, чтобы все мои сценарии были внизу страницы. Поэтому я заставлю мою страницу * _Layout.cshtml * выглядеть так:

_Layout.cshtml:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/css/global.css")" rel="stylesheet" type="text/css" />
</head>
<body>
    <div id="wrapper">
    @RenderBody
    </div>
    <!-- Being a good little web developer, I include my scripts at the BOTTOM, yay!
    -->
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js" type="text/javascript"></script>
</body>
</html>

Но Э-э-э! Что мне теперь делать, потому что мой скрипт показа слайдов оказывается выше моего включения в jQuery ?! Это не было бы большим делом, если бы я хотел, чтобы мое слайд-шоу отображалось на каждой странице, но я хочу, чтобы только частичное представление слайд-шоу отображалось на определенной странице, и… Я ХОЧУ СВОИ СЦЕНАРИИ ВНУТРИ! Что делать?

Ответы [ 2 ]

10 голосов
/ 18 ноября 2011

Вы можете определить раздел на странице макета для сценариев, например, так:

<body>
    <div id="wrapper">
    @RenderBody
    </div>
    <!-- Being a good little web developer, I include my scripts at the BOTTOM, yay!
    -->
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js" type="text/javascript"></script>
    @RenderSection("myScripts")
</body>

Затем на своих страницах вы определяете, что происходит в этом разделе:

@{
    ViewBag.Title = "Slide Show";
}
<div id="slides">
</div>
@section myScripts { //put your scripts here
    <script src="js/slides.min.jquery.js"></script>
    <script type="text/javascript">
    $(function(){
        $('#slides').slides({
            // slide show configuration...
        });
    });
    </script>
}

Затем, когдастраница отобразится, она возьмет все в вашем разделе и добавит его туда, куда она должна перейти на вашей странице макета (в данном случае внизу).

3 голосов
/ 13 февраля 2018

Примечание : принятое решение не будет работать для частичных представлений , когда задается вопрос.

Проблема

В обычном потоке вы можете определить содержимое для определенного раздела из родительского представления вашего ActionResult с помощью объявления @section <i>SectionName</i> {}. И когда это представление, наконец, вставляется в его LayoutPage, оно может вызвать RenderSection, чтобы поместить это содержимое в любое место на странице, позволяя вам определить некоторый встроенный JavaScript, который можно отобразить и проанализировать в нижней части страница после любых основных библиотек, от которых это зависит, вот так:

image Full View">

Проблема возникает, когда вы хотите иметь возможность повторно использовать полный просмотр страницы внутри частичного просмотра. Возможно, вы хотели бы также повторно использовать вид в качестве виджета или диалога внутри другой страницы. В этом случае полное частичное представление отображается полностью, куда бы вы ни отправили вызов @Html.EditorFor или @Html.Partial внутри родительского представления следующим образом:

image Parent View > Partial View">

В соответствии с документами MSDN для макетов с синтаксисом Razor :

  • Разделы, определенные в представлении, доступны только на его непосредственной странице макета.
  • На секции нельзя ссылаться из частичных элементов, компонентов представления или других частей системы представления.
  • Тело и все разделы на странице содержимого должны отображаться на странице макета

В этом случае становится сложным получить сценарий, определенный в частичном представлении внизу страницы. Согласно документам, вы можете вызывать RenderSection только из вида компоновки, и вы не можете определить содержимое @section изнутри частичного представления, поэтому все будет сосредоточено в одной и той же области, и ваш скрипт будет обработан, проанализирован и запущен от середины вашей HTML-страницы, а не снизу, после любых библиотек, от которых она может зависеть.

Решение

Для полного обсуждения многих способов добавления разделов из частичных представлений на вашу страницу я бы начал со следующих двух вопросов о StackOverflow:

Различные решения в них отличаются друг от друга поддержкой вложенности, упорядочивания, поддержкой нескольких сценариев, различными типами содержимого, синтаксисом вызова и возможностью повторного использования. Но как бы вы ни разрезали его, практически любое решение должно будет решить две основные задачи:

  1. Постепенно создавайте объекты скрипта по вашему запросу из любой страницы, частичного представления или шаблона, возможно, используя какое-то расширение HtmlHelper для повторного использования.
  2. Визуализируйте этот объект сценария на странице макета. Поскольку страница макета фактически отображается последней, это просто излучение объекта, который мы создали, на главную страницу.

Вот простая реализация Дарин Димитров

Добавьте вспомогательные методы расширения, которые позволят вам создавать произвольные объекты сценариев в коллекции ViewContent.HttpContext.Items, а затем извлекать и отображать их позже.

Utilities.cs

public static class HtmlExtensions
{
    public static MvcHtmlString Script(this HtmlHelper htmlHelper, Func<object, HelperResult> template)
    {
        htmlHelper.ViewContext.HttpContext.Items["_script_" + Guid.NewGuid()] = template;
        return MvcHtmlString.Empty;
    }

    public static IHtmlString RenderScripts(this HtmlHelper htmlHelper)
    {
        foreach (object key in htmlHelper.ViewContext.HttpContext.Items.Keys)
        {
            if (key.ToString().StartsWith("_script_"))
            {
                var template = htmlHelper.ViewContext.HttpContext.Items[key] as Func<object, HelperResult>;
                if (template != null)
                {
                    htmlHelper.ViewContext.Writer.Write(template(null));
                }
            }
        }
        return MvcHtmlString.Empty;
    }
}

Тогда вы можете использовать это в своем приложении

Создайте объекты этого скрипта внутри своего Частичного представления , например:

<b>@Html.Script(</b>
    <i>@<script>
         $(function() {
             $("#@Html.IdFor(model => model.FirstName)").change(function() {
                 alert("New value is '" + this.value + "'");
             });
         })
     </script></i>
<b>)</b>

А затем визуализируйте их в любом месте в пределах вашей LayoutPage , например:

@Scripts.Render("~/bundles/jquery")
@RenderSection("scripts", required: false)
<b>@Html.RenderScripts()</b>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...