Можно ли разместить JavaScript в частичных представлениях?

Im работает над веб-приложением, где главная страница содержит две части: постоянный блок, который всегда отображается, и информационный блок, составленный одним из трех частичных представлений. Каждый из частичных представлений появляется в результате запроса AJAX и загружается только один раз (после этого окна переключения предоставляются jquery). Он работает хорошо, но Ive столкнулся с одной проблемой.

html-код частичных представлений содержит js-функции, которые также используются в блоке констант и в информационном блоке. Когда страница загружается, эти функции могут "видеть" друг друга, и они работают, но не могут найти объявления функций и предупредить меня об этом. Я не могу решить проблему, передав их во внешний файл js из-за синтаксиса бритвы, который можно найти в их коде.

Что я могу сделать с этим?

Спасибо.

Update:

Наконец, я решил решить проблему, отделяющую мой код js от представлений. Таким образом, новый вопрос заключался в том, как включить синтаксис бритвы в js файлы или что является приемлемой альтернативой. В популярных решениях Ive используются глобальные переменные, атрибуты данных и те, которые мне больше нравятся - библиотека RazorJS от Джона Кациотиса.

http://djsolid.net/blog/razorjs---write-razor-inside-your-javascript-files

Я надеюсь, что он будет работать стабильно и сделать Resharper счастливым.

Ура!

Update:

Спустя 3 года я вспомнил этот вопрос и решил обновить его в соответствии с моим опытом. На самом деле сейчас я бы предпочел не использовать для этого дополнительные библиотеки. Особенно, если вы не единственный член команды проекта... Гораздо лучше, если вы обеспечены во всех своих библиотеках, они поддерживаются создателем и сообществом и могут быть легко интегрированы в вашу среду IDE (например, если используется специальный синтаксис), Также все ребята из вашей команды должны знать, как это работает. Поэтому теперь я предлагаю сделать следующее:

  • Удерживайте все JS в отдельных файлах. Изолируйте его как можно больше. Предоставьте ему внешний API.
  • Вызовите функции API из своих представлений.
  • Передайте все URL-адреса, созданные Razor, текстовые сообщения, константы в качестве параметра ресурса.

Например:

js файл:

$.api.someInitFunction = function(resources){ ... }

Вид:

<script>
    $.api.someInitFunction({
        urls: { myAction: '@Url.Action("MyAction", "MyController")' },
        messages: { error: '@errorMessage' },
        consts: { myConst: @myIntConst }
    });
</script>

Ответ 1

Если Resharper предупреждает вас, что это не большое дело ^ _ ^

Но если бы я был вами, я бы не поставил JavaScript в частичном представлении вообще.

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

И для вашего случая, если вы не можете отделить JavaScript от JS файла, а затем просто создать другой PartialView и поместить в него эти скрипты и просто отобразить его на главной странице.

Ответ 2

Если вы хотите написать частичные представления, которые являются инкапсулированными "виджетами", которые просто работают после включения их на страницу, тогда встраивание блока script внутри частичного представления - это один чистый способ обернуть разметку и инициализацию script вместе в частичном представлении. Например, у меня может быть частичное представление с именем "_EventList", которое я использую на своем сайте. Если я помещаю в два места на моей главной странице, он должен работать, и я предпочитаю не писать логику на моей главной странице, чтобы инициализировать виджет.

Если вы никогда не будете использовать его более одного раза на странице, это просто. Но если вы можете, то оберните script, чтобы он не выполнялся дважды. Смотри ниже. Для фрагментов Qaru я имитирую его, повторяя частичный вид дважды в фрагменте кода для представления, включая частичный вид дважды на главной странице.

Моя главная страница может выглядеть так:

<div id="left-nav">
   @Html.Partial("_EventList")           
</div>

<div id="body">
</div>

<div id="right-nav">
   @Html.Partial("_EventList")
</div>

Пример:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<!-- Self-contained partial view containing widget -->

<div id="widgetDiv" class="panel panel-default">

    <div class="panel-heading">Event Dates</div>
    <div class="panel panel-group">
       <ul class="widget">
         <!-- These will load dynamically -->
       </ul>
    </div>

    <script>
        $(document).ready(function() {

            // Run this once only in case widget is on page more than once
            if(typeof $widget == 'undefined') {
                $widget = $("ul.widget"); // could be more than one
                // mock data to simulate an ajax call
                var data = [
                   {Description: "March", StartDate: "03/01/2015"},
                   {Description: "April", StartDate: "04/01/2015"},
                   {Description: "May", StartDate: "05/01/2015"}
                ];

                $.each($widget, function(w, widget) {
                    // might be an $.ajax call
                    $.each(data, function(i, row) {
                        $(widget).append("<li><a href='/Widget/Search?startDate=" + row.StartDate + "'>" + row.Description + "</a></li>");
                    });
                });
            }
        });
    </script>
</div>
<!-- End of widget / partial view -->



<!-- Second copy of above for sake of example snippet -->
<!-- No need to read further -->









<!-- Self-contained partial view containing widget -->

<div id="widgetDiv" class="panel panel-default">

    <div class="panel-heading">Event Dates</div>
    <div class="panel panel-group">
       <ul class="tinylist nav nav-sidebar widget">
         <!-- These will load dynamically -->
       </ul>
    </div>

    <script>
        $(document).ready(function() {

            // Run this once only in case widget is on page more than once
            if(typeof $widget == 'undefined') {
                $widget = $("ul.widget"); // could be more than one
                // mock data to simulate an ajax call
                var data = [
                   {Description: "March", StartDate: "03/01/2015"},
                   {Description: "April", StartDate: "04/01/2015"},
                   {Description: "May", StartDate: "05/01/2015"}
                ];

                $.each($widget, function(w, widget) {
                    // might be an $.ajax call
                    $.each(data, function(i, row) {
                        $(widget).append("<li><a href='/Widget/Search?startDate=" + row.StartDate + "'>" + row.Description + "</a></li>");
                    });
                });
            }
        });
    </script>
</div>
<!-- End of widget / partial view -->

Ответ 3

Я согласен с Вахидом в том, что вы не должны ставить JavaScript во взглядах на частичное или иное. Я видел достаточно кода, который делает это, чтобы знать, что это ничего не значит.

Я бы также сказал, что вы должны иметь возможность передавать логику, инкапсулированную в синтаксисе Razor, в JavaScript, вам просто нужно передать на ваш JavaScript информацию, необходимую вашей логике.

Я просто догадываюсь из опыта этого следующего комментария, но вы должны спроектировать JavaScript так же, как и при проектировании структуры кода С# или VB.NET. Таким образом, логика, которую вы используете Razor для, должна быть частью вашего JavaScript.

Таким образом, ваш JavaScript будет легче поддерживать, и я полагаю, что Resharper также должен быть более счастливым.

Ответ 4

Я делаю это и считаю это очень удобным. Он отлично работает, чтобы динамически загружать частичные фрагменты javascript с доступностью ViewBag, HttpContext и т.д.

Это приводит к чему-то, что похоже на использование T4-шаблонов.

Вы даже можете получить валидацию javascript, intellisense и т.д., если вы добавите теги phantom script, как это.

@using System.Configuration
@if (false)
{
    @:<script type="text/javascript">
}    
        $scope.clickCartItem = function(cartItem) {
            console.log(cartItem);
            window.location.href [email protected]("('" + ConfigurationManager.AppSettings["baseUrl"] + "/Checkout/' + cartItem.ItemId)");
        };
        dataAccess.getCart(
        function (response) {
            //...
        },
        function (response) {
            //...
        }
        );

@if (false)
{
    @:</script>
}