asp.net-mvc: символ бритвы '@' в файле js

90

У меня есть .csHtmlфайл -razor с функцией javascript, которая использует @Url.Contentфункцию C # внутри для URL-адреса ajax.
Я хочу переместить эту функцию в .jsфайл, на который я ссылаюсь.

Проблема в том, что javascript не «знает» @символ и не анализирует код C #.
Есть ли способ ссылаться на .jsфайлы с помощью символа «@»?

gdoron поддерживает Монику
источник
2
Возможно, это поможет (см. Ответ) stackoverflow.com/questions/7892793/ajax-succes-function
Андрей Христянович

Ответы:

87

Вы можете использовать data-*атрибуты HTML5 . Предположим, вы хотите выполнить какое-то действие при щелчке по некоторому элементу DOM, например, div. Так:

<div id="foo" data-url="@Url.Content("~/foobar")">Click me</div>

а затем в вашем отдельном файле javascript вы можете ненавязчиво работать с DOM:

$('#foo').click(function() {
    var url = $(this).data('url');
    // do something with this url
});

Таким образом, у вас может быть чистое разделение между разметкой и скриптом без необходимости использования каких-либо серверных тегов в ваших файлах javascript.

Дарин Димитров
источник
Благодарю. Думаю, для нескольких значений может быть головная боль. Сначала я подумал, что это может решить мою проблему, но после этой попытки я нашел так много ссылок в моем коде и решил найти другой способ.
QMaster
19

Что ж, я только что нашел на nuget двигатель бритвы, который делает это! Значение решает @синтаксис!
Его зовут RazorJS .

NuGet пакет


Обновление 2016:
пакет не обновлялся 5 лет, ссылка на сайт проекта мертва. Я не рекомендую больше использовать эту библиотеку.

gdoron поддерживает Монику
источник
Вы можете разобраться в этом? stackoverflow.com/questions/27702322/…
Кодер
Первая ссылка не работает
Мемет Олсен
@MemetOlsen, действительно, извините, но я не могу найти его копию, поэтому я удалил ее :(
gdoron поддерживает Монику
@gdoron, без проблем. Я просто хотел сообщить вам о неработающей ссылке. Как вы сказали, пакет не обновлялся 5 лет, поэтому, вероятно, использовать его в любом случае - плохая идея.
Мемет Олсен
10

Один из способов решения проблемы:

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

gdoron поддерживает Монику
источник
9

У вас есть два варианта:

  • Используйте значение в качестве параметра функции и подключения в представлении
  • Создайте пространство имен (вместо переменной общедоступного уровня, которая считается плохой практикой в ​​JS) и установите это значение в верхней части страницы, а затем используйте его в своих js

Например:

 var MyCompany = 
 {
   MyProject: {
                  MyVariable:""
               }
  };

А затем, на ваш взгляд, установите его:

MyCompany.MyProject.MyVariable = @....

ОБНОВИТЬ

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

В любом случае есть третий вариант - создать движок просмотра и запустить js-файлы против бритвы и отправить результаты обратно. Это чище, но намного медленнее, поэтому не рекомендуется.

Алиостад
источник
1
+1 Делаю первый способ. Вызовите функцию инициализации из своего представления, передав все требуемые данные.
Ричард Далтон,
Спасибо, второй подход - неплохая связь между представлением и файлом js? У тебя есть способ получше?
gdoron поддерживает Монику
Оба связаны. Невозможно разъединить, если вы не напишете движок представления для обработки файлов js перед рендерингом. Смотрите мои обновления.
Aliostad
как насчет того способа, который я предложил? stackoverflow.com/questions/7902213/…
gdoron поддерживает Монику
Звучит нормально. Мой +1. Либо частичный, либо полный просмотр, ничего не меняет. Все это связано с js.
Aliostad
7

Чтобы поместить @переменную в ваш .js файл, вам нужно будет использовать глобальную переменную и установить значение этой переменной из представления mvc, которое использует этот файл .js.

Файл JavaScript:

var myValue;

function myFunc() {
  alert(myValue);
}

Файл представления MVC:

<script language="text/javascript">
    myValue = @myValueFromModel;
</script>

Просто убедитесь, что любые вызовы вашей функции происходят ПОСЛЕ того, как значение было установлено представлением.

Джоэл Этертон
источник
1
как насчет непосредственной передачи myValue в качестве параметра функции? Я предпочитаю иметь явный вызов с параметром, чем полагаться на глобальные переменные, однако я не очень увлечен javascript, поэтому мне может не хватать какого-то важного аспекта наличия глобального.
BigMike
@BigMike: Конечно, приемлемо. Метод, который я изложил выше, просто делает переменную доступной для нескольких функций одновременно, но использование параметров также хорошо.
Джоэл Этертон
Спасибо за разъяснение. Было бы здорово иметь какую-то версию модели js-объекта автоматически (с помощью атрибутов в классе модели будет здорово), это просто добавит шаблон и решение переменной, полностью учитывающее пространство имен. Я предполагаю, что большая проблема будет заключаться в том, как внедрить код в сгенерированный html, отправленный в браузер (напрямую через тег <script>). Думаю, я проведу над этим несколько экспериментов, как только мой текущий проект будет завершен.
BigMike
@BigMike: это должно быть довольно легко сделать с помощью класса DataContractJsonSerializer ( msdn.microsoft.com/en-us/library/… ). Это создаст версию JSON вашего класса, которую можно будет проанализировать в представлении.
Джоэл Этертон
4

Наверное, это неправильный подход. Учитывая разделение проблем. Вы должны иметь data injectorна своем JavaScriptклассе , и которые в большинстве случаев данные является JSON.

Создайте файл JS в своей scriptпапке и добавьте эту ссылку в свойView

<script src="@Url.Content("~/Scripts/yourJsFile.js")" type="text/javascript"></script>

Теперь рассмотрим JavaScriptбуквальный класс в вашем yourJsFile.js:

var contentSetter = {
    allData: {},
    loadData: function (data) {
        contentSetter.allData = eval('(' + data + ')');
    },
    setContentA: function () {
        $("#contentA").html(allData.contentAData);
    },
    setContentB: function () {
        $("#contentB").html(allData.contentAData);
    }
};

Также объявите класс

public class ContentData
{
    public string ContentDataA { get; set }
    public string ContentDataB { get; set }
}

Теперь, Actionсделайте это:

public ActionResult Index() {
    var contentData = new ContentData();
    contentData.ContentDataA = "Hello";
    contentData.ContentDataB = "World";
    ViewData.Add("contentData", contentData);
}

И с вашей точки зрения:

<div id="contentA"></div>
<div id="contentB"></div>

<script type="text/javascript">
    contentSetter.loadData('@Json.Encode((ContentData) ViewData["contentData"])');
    contentSetter.setContentA();
    contentSetter.setContentB();
</script>
Абдул Муним
источник
Ницца! но я думаю, что это слишком сложно ... что вы думаете о моем ответе? stackoverflow.com/questions/7902213/… . кстати, у вас есть ошибка копирования и вставки в setContentB, вы написали contentAData. спасибо!
gdoron поддерживает Монику
1
@gdoron Поверьте, управление классами JS и рассмотрение разделения - это спасение, когда у вас есть огромный проект
Абдул Муним
4

Недавно я писал в блоге на эту тему: Создание внешних файлов JavaScript с использованием частичных представлений Razor .

Мое решение - использовать настраиваемый атрибут ( ExternalJavaScriptFileAttribute), который отображает частичное представление Razor как есть, а затем возвращает его без окружающих <script>тегов. Это делает его допустимым внешним файлом JavaScript.

Мариус Шульц
источник
2

Я обычно оборачиваю JS, требующий доступа к свойствам модели, в функциях, а затем передаю @something в представлении. Например

<script type="text/javascript">
function MyFunction(somethingPresentInTheView) {
  alert(somethingPresentInTheView);
}
</script>

в представлении я добавляю вызов функции через (просто пример):

<input type='button' onclick="MyFunction('@Model.PropertyNeeded')" />
BigMike
источник
1

Я думаю, вы застряли в том, чтобы поместить этот код JS в представление. Насколько мне известно, парсер Razor не будет просматривать файлы .js, поэтому все, что у вас есть @, не будет работать. Плюс, как вы заметили, сам Javascript не любит, чтобы этот @персонаж торчал без причины, кроме, скажем, строки.

Джейсон Эванс
источник