asp.net-mvc: символ `` @ '' у файлі js


90

У мене є .csHtmlфайл -razor з функцією javascript, який використовує функцію @Url.ContentC # всередині 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 Я роблю перший метод. Викличте функцію ініціалізації з вашого подання, передаючи всі потрібні вам дані.
Richard Dalton

Дякуємо, другий підхід - це не погане поєднання між поданням та js-файлом? У вас є кращий спосіб?
gdoron підтримує Моніку

Обидва є зчепленням. Неможливо роз’єднатись, якщо ви не напишете механізм перегляду для обробки файлів js перед рендерингом. Перегляньте мої оновлення.
Аліостад,

а як щодо цього способу, який я запропонував? stackoverflow.com/questions/7902213 / ...
gdoron підтримує Моніка

Звучить нормально. Мій +1. Часткове або повне представлення нічого не змінює. Це все поєднання подання з js.
Аліостад

7

Для того, щоб отримати @змінну у своєму .js-файлі, вам доведеться використовувати глобальну змінну та встановити значення цієї змінної у поданні mvc, яке використовує цей .js-файл.

Файл JavaScript:

var myValue;

function myFunc() {
  alert(myValue);
}

MVC Переглянути файл:

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

Тільки переконайтеся, що будь-які дзвінки до вашої функції відбуваються ПІСЛЯ значення, встановленого видом.


1
як щодо передачі безпосередньо myValue як параметра функції? Я вважаю за краще мати явні дзвінки з param, ніж покладатися на глобальні, проте я не настільки зацікавлений у 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 із використанням часткових подань бритви .

Моє рішення полягає у використанні користувацького атрибута ( 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.