asp.net-mvc: Rasiermessersymbol '@' in js-Datei

90

Ich habe eine .csHtml-razor-Datei mit einer Javascript-Funktion, die die darin enthaltene @Url.ContentC # -Funktion für die Ajax-URL verwendet.
Ich möchte diese Funktion in eine .jsDatei verschieben, auf die aus meiner Sicht verwiesen wird.

Das Problem ist, dass Javascript das @Symbol nicht "kennt" und den C # -Code nicht analysiert.
Gibt es eine Möglichkeit, .jsDateien aus der Ansicht mit dem Symbol "@" zu referenzieren ?

Gdoron unterstützt Monica
quelle
2
Vielleicht hilft dies (siehe Antwort) stackoverflow.com/questions/7892793/ajax-succes-function
Andriy Khrystyanovich

Antworten:

87

Sie können HTML5- data-*Attribute verwenden. Angenommen, Sie möchten eine Aktion ausführen, wenn auf ein DOM-Element wie ein div geklickt wird. So:

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

und dann könnten Sie in Ihrer separaten Javascript-Datei unauffällig mit dem DOM arbeiten:

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

Auf diese Weise können Sie eine reine Trennung zwischen Markup und Skript erzielen, ohne dass Sie jemals serverseitige Tags in Ihren Javascript-Dateien benötigen.

Darin Dimitrov
quelle
Vielen Dank. Ich denke für mehrere Werte kann Kopfschmerzen sein. Zuerst dachte ich, es könnte mein Problem lösen, aber nachdem ich es ausprobiert hatte, fand ich so viele Verweise in meinem Code und beschloss, einen anderen Weg zu finden.
QMaster
19

Nun, ich habe gerade einen Rasierermotor auf Nuget gefunden, der das macht! Bedeutung löst @Syntax!
Es heißt RazorJS .

Das Nuget- Paket


Update 2016:
Das Paket wurde 5 Jahre lang nicht aktualisiert und der Link zur Projektsite ist tot. Ich empfehle nicht mehr, diese Bibliothek zu benutzen.

Gdoron unterstützt Monica
quelle
Kannst du das untersuchen? stackoverflow.com/questions/27702322/…
iamCR
Erster Link ist defekt
Memet Olsen
@MemetOlsen, tut mir leid, aber ich kann keine Kopie davon finden, also habe ich sie entfernt :(
gdoron unterstützt Monica am
@gdoron, kein Problem. Ich wollte dich nur über den toten Link informieren. Wie Sie bereits sagten, wurde das Paket 5 Jahre lang nicht aktualisiert, daher ist es wahrscheinlich eine schlechte Idee, es trotzdem zu verwenden.
Memet Olsen
10

Eine Möglichkeit , das Problem anzugehen, ist:

Hinzufügen einer Teilansicht mit den Javascript-Funktionen zur Ansicht.
Auf diese Weise können Sie das @Symbol verwenden und alle Ihre javascriptFunktionen werden von der Ansicht getrennt.

Gdoron unterstützt Monica
quelle
9

Sie haben zwei Möglichkeiten:

  • Verwenden Sie den Wert als Parameter in der Funktion und verkabeln Sie ihn in der Ansicht
  • Erstellen Sie einen Namespace (anstelle einer Variablen auf öffentlicher Ebene, die in JS als schlechte Praxis angesehen wird), setzen Sie diesen Wert oben auf der Seite und verwenden Sie ihn dann in Ihrem js

Beispielsweise:

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

Und dann setzen Sie es aus Ihrer Sicht:

MyCompany.MyProject.MyVariable = @....

AKTUALISIEREN

Sie mögen sich fragen, ob keiner wegen der Kopplung etwas Gutes ist. Nun, es ist wahr, Sie koppeln js und view. Aus diesem Grund müssen Skripte den Speicherort, an dem sie ausgeführt werden, nicht kennen, damit es sich um einen handelt Symptom für eine nicht optimale Organisation von Dateien.

Auf jeden Fall gibt es eine dritte Option, um eine Ansichts-Engine zu erstellen und die js-Dateien gegen den Rasierer auszuführen und die Ergebnisse zurückzusenden. Dies ist sauberer, aber viel langsamer und wird daher auch nicht empfohlen.

Aliostad
quelle
1
+1 Ich mache die erste Methode. Rufen Sie aus Ihrer Sicht eine Initialisierungsfunktion auf, die alle erforderlichen Daten übergibt.
Richard Dalton
Danke, der zweite Ansatz ist keine schlechte Kopplung zwischen der Ansicht und der js-Datei? Hast du einen besseren Weg?
Gdoron unterstützt Monica
Beide koppeln. Es gibt keine Möglichkeit zum Entkoppeln, es sei denn, Sie schreiben eine Ansichts-Engine, um js-Dateien vor dem Rendern zu verarbeiten. Siehe meine Updates.
Aliostad
Was ist mit diesem Weg, den ich vorgeschlagen habe? stackoverflow.com/questions/7902213/…
gdoron unterstützt Monica
Klingt in Ordnung. Meine +1. Die Teil- oder Vollansicht ändert nichts. Es ist alles Kopplungsansicht mit js.
Aliostad
7

Um die @Variable in Ihre .js-Datei aufzunehmen, müssen Sie eine globale Variable verwenden und den Wert dieser Variablen in der MVC-Ansicht festlegen, die diese .js-Datei verwendet.

JavaScript-Datei:

var myValue;

function myFunc() {
  alert(myValue);
}

MVC View-Datei:

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

Stellen Sie nur sicher, dass alle Aufrufe Ihrer Funktion erfolgen, nachdem der Wert in der Ansicht festgelegt wurde.

Joel Etherton
quelle
1
Was ist mit der direkten Übergabe von myValue als Parameter an die Funktion? Ich ziehe es vor, explizit mit param anzurufen, anstatt mich auf Globals zu verlassen, aber ich bin nicht so begeistert von Javascript, so dass mir möglicherweise ein wichtiger Aspekt eines Global fehlt.
BigMike
@ BigMike: Auf jeden Fall akzeptabel. Die oben beschriebene Methode stellt die Variable einfach mehreren Funktionen gleichzeitig zur Verfügung, aber die Verwendung von Parametern ist genauso gut.
Joel Etherton
Danke für die Klarstellung. Es wäre großartig, automatisch eine Art js-Objektversion des Modells zu haben (über Attribute in der Modellklasse ist dies großartig). Dies fügt lediglich ein Muster und eine vollständig namespace-fähige Variablenlösung hinzu. Ich denke, das große Problem wäre, wie man den Code in das generierte HTML einfügt, das an den Browser gesendet wird (direkt über das <script> -Tag). Ich denke, ich werde einige Experimente dazu durchführen, sobald mein aktuelles Projekt beendet ist.
BigMike
@BigMike: Dies sollte mithilfe der DataContractJsonSerializer- Klasse ( msdn.microsoft.com/en-us/library/… ) recht einfach zu bewerkstelligen sein . Es würde eine JSON-Version Ihrer Klasse erstellen, die in die Ansicht analysiert werden könnte.
Joel Etherton
4

Wahrscheinlich ist dies nicht der richtige Ansatz. Berücksichtigung der Trennung von Bedenken. Sie sollten eine data injectorin Ihrer JavaScriptKlasse haben und das sind in den meisten Fällen Daten JSON.

Erstellen Sie eine JS-Datei in Ihrem scriptOrdner und fügen Sie diesen Verweis zu Ihrem hinzuView

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

Betrachten Sie nun eine JavaScriptwörtliche Klasse in Ihrem yourJsFile.js:

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

Deklarieren Sie auch eine Klasse

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

Nun, von Ihnen aus Actiontun Sie dies:

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

Und aus Ihrer Sicht:

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

<script type="text/javascript">
    contentSetter.loadData('@Json.Encode((ContentData) ViewData["contentData"])');
    contentSetter.setContentA();
    contentSetter.setContentB();
</script>
Abdul Munim
quelle
Nett! aber ich denke es ist zu kompliziert ... was denkst du über meine Antwort? stackoverflow.com/questions/7902213/… . Übrigens, Sie haben einen Fehler beim Kopieren und Einfügen in setContentB. Sie haben contentAData geschrieben. danken!
Gdoron unterstützt Monica
1
@gdoron Glauben Sie mir, JS-Klassen zu verwalten und Trennung in Betracht zu ziehen, ist ein Lebensretter, wenn Sie ein großes Projekt haben
Abdul Munim
4

Ich habe kürzlich über dieses Thema gebloggt: Generieren externer JavaScript-Dateien mit partiellen Rasiermesseransichten .

Meine Lösung besteht darin, ein benutzerdefiniertes Attribut ( ExternalJavaScriptFileAttribute) zu verwenden, das eine teilweise Razor-Ansicht unverändert rendert und sie dann ohne die umgebenden <script>Tags zurückgibt . Das macht es zu einer gültigen externen JavaScript-Datei.

Marius Schulz
quelle
2

Normalerweise verpacke ich JS, das Zugriff auf Modelleigenschaften benötigt, in Funktionen und übergebe dann das @something in der Ansicht. Beispielsweise

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

In der Ansicht füge ich einen Funktionsaufruf hinzu über (nur ein Beispiel):

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

Ich denke, Sie müssen diesen JS-Code nicht mehr in die Ansicht einfügen. Der Razor-Parser wird meines Wissens keine .js-Dateien anzeigen, daher funktioniert alles, was Sie verwenden @, nicht. PLus, wie Sie gesehen haben, mag Javascript selbst dieses @Zeichen nicht ohne Grund, außer zum Beispiel in einer Zeichenfolge.

Jason Evans
quelle