asp.net-mvc: symbol „@” razor w pliku js


90

Mam .csHtmlplik -razor z funkcją javascript, która używa funkcji @Url.ContentC # wewnątrz dla adresu URL ajax.
Chcę przenieść tę funkcję do .jspliku, do którego odwołuje się mój widok.

Problem polega na tym, że javascript nie „zna” @symbolu i nie analizuje kodu C #.
Czy istnieje sposób odwoływania się do .jsplików z widoku za pomocą symbolu „@”?


Odpowiedzi:


87

Możesz użyć data-*atrybutów HTML5 . Załóżmy, że chcesz wykonać jakąś akcję po kliknięciu jakiegoś elementu DOM, takiego jak div. Więc:

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

a następnie w oddzielnym pliku javascript możesz dyskretnie pracować z DOM:

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

W ten sposób możesz mieć czystą separację między znacznikami a skryptem bez konieczności stosowania jakichkolwiek tagów po stronie serwera w plikach javascript.


Dzięki. Myślę, że dla wielu wartości może być ból głowy. Po pierwsze pomyślałem, że może to rozwiązać mój problem, ale po spróbowaniu znalazłem tak wiele poleceń w moim kodzie i postanowiłem znaleźć inny sposób.
— QMaster

19

Cóż, właśnie znalazłem silnik maszynki do golenia na Nuget, który to robi! Znaczenie rozwiązuje @składnię!
Nazywa się RazorJS .

Nuget pakiet


Aktualizacja 2016:
pakiet nie był aktualizowany przez 5 lat, a link do witryny projektu jest martwy. Nie polecam już ludziom korzystania z tej biblioteki.


Możesz się temu przyjrzeć? stackoverflow.com/questions/27702322/…
— Coder

Pierwszy link jest uszkodzony
— Memet Olsen

@MemetOlsen, rzeczywiście, przepraszam, ale nie mogę znaleźć jego kopii, więc go usunąłem :(
— gdoron wspiera Monikę

@gdoron, nie ma problemu. Chciałem tylko poinformować cię o martwym łączu. Jak już wspomniałeś, pakiet nie był aktualizowany przez 5 lat, więc prawdopodobnie i tak jest złym pomysłem.
— Memet Olsen

10

Jednym ze sposobów rozwiązania tego problemu jest:

Dodanie częściowego widoku z funkcjami javascript do widoku.
W ten sposób możesz użyć @symbolu, a wszystkie javascriptfunkcje są oddzielone od widoku.


9

Masz dwie możliwości:

  • Użyj wartości jako parametru w funkcji i połącz w widoku
  • Utwórz przestrzeń nazw (zamiast zmiennej poziomu publicznego, która jest uważana za złą praktykę w JS) i ustaw tę wartość na górze strony, a następnie użyj jej w swoim js

Na przykład:

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

A potem twoim zdaniem ustaw to:

MyCompany.MyProject.MyVariable = @....

AKTUALIZACJA

Możesz się zastanawiać, że żadna z nich nie jest dobra ze względu na połączenie, cóż, to prawda, łączysz js i widok. Dlatego skrypty muszą być nieświadome lokalizacji, w której działają, więc jest to objaw nieoptymalnej organizacji plików.

W każdym razie istnieje trzecia opcja, aby utworzyć silnik widoku i uruchomić pliki js na maszynce do golenia i odesłać wyniki. Jest to czystsze, ale znacznie wolniejsze, więc też nie jest zalecane.


1
+1 Robię pierwszą metodę. Wywołaj funkcję inicjalizacyjną z poziomu swojego widoku, przekazując wszystkie wymagane dane.
— Richard Dalton

Dzięki, drugie podejście nie jest złym sprzężeniem między widokiem a plikiem js? Czy masz lepszy sposób?
— gdoron wspiera Monikę

Oba są sprzężeniem. Nie ma możliwości odłączenia, chyba że napiszesz silnik widoku do przetwarzania plików js przed renderowaniem. Zobacz moje aktualizacje.
— Aliostad

co z tą drogą, którą zaproponowałem? stackoverflow.com/questions/7902213/ ...
— gdoron wspiera Monikę

Brzmi dobrze. Moje +1. Widok częściowy lub pełny niczego nie zmienia. To wszystko jest sprzężeniem z js.
— Aliostad

7

Aby @umieścić zmienną w pliku .js, musisz użyć zmiennej globalnej i ustawić wartość tej zmiennej z widoku mvc, który korzysta z tego pliku .js.

Plik JavaScript:

var myValue;

function myFunc() {
  alert(myValue);
}

Plik widoku MVC:

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

Po prostu upewnij się, że wszelkie wywołania Twojej funkcji następują PO ustawieniu wartości przez widok.


1
a co z przekazaniem bezpośrednio myValue jako parametru do funkcji? Wolę mieć wyraźne wywołanie z param niż poleganie na globals, jednak nie jestem zbytnio zainteresowany JavaScriptem, więc może brakuje mi jakiegoś ważnego aspektu posiadania globalnego.
— BigMike

@BigMike: Z pewnością do zaakceptowania. Metoda, którą przedstawiłem powyżej, po prostu sprawia, że ​​zmienna jest dostępna dla wielu funkcji jednocześnie, ale używanie parametrów jest równie dobre.
— Joel Etherton

dzięki za wyjaśnienie. Byłoby wspaniale mieć jakąś wersję modelu obiektu js automatycznie (poprzez Attributes w klasie modelu będzie świetnie), to po prostu doda wzorzec i rozwiązanie w pełni uwzględniające przestrzeń nazw. Myślę, że dużym problemem byłoby wstrzyknięcie kodu w wygenerowanym html wysłanym do przeglądarki (bezpośrednio przez tag <script>). Myślę, że przeprowadzę na tym trochę eksperymentów, gdy tylko mój obecny projekt się zakończy.
— BigMike

@BigMike: Powinno to być dość łatwe do osiągnięcia przy użyciu klasy DataContractJsonSerializer ( msdn.microsoft.com/en-us/library/… ). Stworzyłoby to wersję JSON twojej klasy, którą można byłoby przeanalizować w widoku.
— Joel Etherton

4

Prawdopodobnie nie jest to właściwe podejście. Rozważenie rozdzielenia obaw. Powinieneś mieć data injectorna swojej JavaScriptklasie i która jest w większości przypadków danymi JSON.

Utwórz plik JS w swoim scriptfolderze i dodaj to odniesienie do swojegoView

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

Rozważ teraz JavaScriptdosłowną klasę w swoim yourJsFile.js:

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

Zadeklaruj również klasę

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

Teraz Actionzrób to:

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

I z twojego punktu widzenia:

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

<script type="text/javascript">
    contentSetter.loadData('@Json.Encode((ContentData) ViewData["contentData"])');
    contentSetter.setContentA();
    contentSetter.setContentB();
</script>

Ładny! ale myślę, że to zbyt skomplikowane ... co myślisz o mojej odpowiedzi? stackoverflow.com/questions/7902213/… . tak przy okazji masz błąd kopiowania wklejania w setContentB, napisałeś contentAData. podziękować!
— gdoron wspiera Monikę

1
@gdoron Uwierz mi, zarządzanie klasami JS i rozważanie separacji ratuje życie, gdy masz duży projekt
— Abdul Munim


2

Zwykle pakuję JS, potrzebując dostępu do właściwości modelu, w funkcje, a następnie przekazuję @something w widoku. Na przykład

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

w widoku dodaję wywołanie funkcji za pośrednictwem (tylko przykład):

<input type='button' onclick="MyFunction('@Model.PropertyNeeded')" />

1

Myślę, że utknąłeś z koniecznością umieszczenia tego kodu JS w widoku. O ile wiem, parser Razor nie będzie przeglądał plików .js, więc wszystko, co masz @, nie zadziała. PLus, jak zauważyłeś, sam Javascript nie lubi tej @postaci kręcącej się bez powodu, inaczej niż, powiedzmy, w ciągu.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.