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


90

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

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


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 лет, ссылка на сайт проекта мертва. Я не рекомендую больше использовать эту библиотеку.


Вы можете разобраться в этом? stackoverflow.com/questions/27702322/…
— Кодер

Первая ссылка не работает
— Мемет Олсен

@MemetOlsen, действительно, извините, но я не могу найти его копию, поэтому я удалил ее :(
— gdoron поддерживает Монику

@gdoron, без проблем. Я просто хотел сообщить вам о неработающей ссылке. Как вы сказали, пакет не обновлялся 5 лет, поэтому, вероятно, использовать его в любом случае - плохая идея.
— Мемет Олсен

10

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

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


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')" />

1

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.