asp.net-mvc: simbolo "@" razor nel file js


90

Ho un .csHtmlfile -razor con una funzione javascript che utilizza la @Url.Contentfunzione C # all'interno per l'URL ajax.
Voglio spostare quella funzione in un .jsfile referenziato dalla mia vista.

Il problema è che javascript non "conosce" il @simbolo e non analizza il codice C #.
C'è un modo per fare riferimento ai .jsfile dalla vista con il simbolo "@"?


Risposte:


87

Potresti usare data-*attributi HTML5 . Supponiamo che tu voglia eseguire un'azione quando si fa clic su un elemento DOM come un div. Così:

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

e poi nel tuo file javascript separato potresti lavorare in modo discreto con il DOM:

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

In questo modo potresti avere una separazione pura tra markup e script senza che tu abbia mai bisogno di tag lato server nei tuoi file javascript.


Grazie. Penso che per più valori possa essere un mal di testa. In primo luogo ho pensato che potesse risolvere il mio problema, ma dopo aver provato ho trovato così tanti riferimenti nel mio codice e ho deciso di trovare un altro modo.
QMaster

19

Beh, ho appena trovato un motore a rasoio su nuget che lo fa! Il significato risolve la @sintassi!
Il suo nome è RazorJS .

Il pacchetto Nuget


Aggiornamento 2016:
il pacchetto non è stato aggiornato per 5 anni e il collegamento al sito del progetto è morto. Non consiglio alle persone di usare più questa libreria.



Primo collegamento interrotto
Memet Olsen

@MemetOlsen, in effetti, mi dispiace ma non riesco a trovarne una copia, quindi l'ho rimosso :(
gdoron sta supportando Monica

@gdoron, nessun problema. Volevo solo farti sapere del collegamento morto. Come hai affermato, il pacchetto non è stato aggiornato per 5 anni, quindi probabilmente è una cattiva idea usarlo comunque.
Memet Olsen

10

Un modo per affrontare il problema è:

Aggiunta di una vista parziale con le funzioni javascript alla vista.
In questo modo puoi usare il @simbolo e tutte le tue javascriptfunzioni sono separate dalla vista.


9

Hai due opzioni:

  • Utilizzare il valore come parametro nella funzione e collegare nella vista
  • Crea uno spazio dei nomi (invece di una variabile di livello pubblico che è considerata una cattiva pratica in JS) e imposta questo valore nella parte superiore della pagina e quindi usalo nel tuo js

Per esempio:

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

E poi, secondo te, impostalo:

MyCompany.MyProject.MyVariable = @....

AGGIORNARE

Potresti chiederti che nessuno è buono a causa dell'accoppiamento, beh è vero, stai accoppiando js e view. Questo è il motivo per cui gli script devono essere ignari della posizione in cui vengono eseguiti, quindi è un sintomo di un'organizzazione non ottimale dei file.

Comunque c'è una terza opzione per creare un motore di visualizzazione ed eseguire i file js contro il rasoio e inviare i risultati indietro. Questo è più pulito ma molto più lento, quindi non consigliato.


1
+1 Faccio il primo metodo. Chiama una funzione di inizializzazione dalla tua vista passando tutti i dati di cui hai bisogno.
Richard Dalton

Grazie, il secondo approccio non è un cattivo accoppiamento tra la vista e il file js? Hai un modo migliore?
gdoron supporterà Monica il

Entrambi si stanno accoppiando. Non c'è modo di disaccoppiare a meno che non si scriva un motore di visualizzazione per elaborare i file js prima del rendering. Vedi i miei aggiornamenti.
Aliostad

che dire di questo modo che ho suggerito? stackoverflow.com/questions/7902213/...
gdoron sostiene Monica

Va bene. Il mio +1. Sia la visualizzazione parziale che quella completa, non cambia nulla. È tutta vista di accoppiamento con js.
Aliostad

7

Per ottenere la @variabile nel tuo file .js dovrai usare una variabile globale e impostare il valore di quella variabile dalla vista mvc che sta usando quel file .js.

File JavaScript:

var myValue;

function myFunc() {
  alert(myValue);
}

File di visualizzazione MVC:

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

Assicurati solo che qualsiasi chiamata alla tua funzione avvenga DOPO che il valore è stato impostato dalla vista.


1
che ne dici di passare direttamente myValue come parametro alla funzione? Preferisco avere chiamate esplicite con param piuttosto che fare affidamento su globali, tuttavia non sono così appassionato di javascript quindi potrei perdere alcuni aspetti importanti di avere un globale.
BigMike

@ BigMike: sicuramente accettabile. Il metodo che ho esposto sopra rende semplicemente la variabile disponibile per più funzioni contemporaneamente, ma l'uso dei parametri è altrettanto buono.
Joel Etherton

grazie per il chiarimento. Sarebbe bello avere automaticamente una sorta di versione dell'oggetto js del modello (tramite Attributes nella classe del modello sarà fantastico), questo aggiungerà semplicemente un pattern e una soluzione variabile completamente consapevole dello spazio dei nomi. Immagino che il grosso problema sarebbe come iniettare il codice nell'html generato inviato al browser (direttamente tramite il tag <script>). Penso che eseguirò alcuni esperimenti su questo non appena il mio progetto attuale sarà finito.
BigMike

@ BigMike: dovrebbe essere abbastanza semplice da eseguire utilizzando la classe DataContractJsonSerializer ( msdn.microsoft.com/en-us/library/… ). Creerebbe una versione JSON della tua classe che potrebbe essere analizzata nella vista.
Joel Etherton

4

Probabilmente questo non è l'approccio giusto. Considerando la separazione delle preoccupazioni. Dovresti avere un data injectorsulla tua JavaScriptclasse e che nella maggior parte dei casi è i dati JSON.

Crea un file JS nella tua scriptcartella e aggiungi questo riferimento al tuoView

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

Ora, considera una JavaScriptclasse letterale nel tuo yourJsFile.js:

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

Dichiara anche una classe

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

Ora, dal tuo Actionfai questo:

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

E dal tuo punto di vista:

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

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

Bello! ma penso che sia troppo complicato ... cosa ne pensi della mia risposta? stackoverflow.com/questions/7902213/… . a proposito, hai un errore di copia incolla in setContentB hai scritto contentAData. grazie!
gdoron supporterà Monica il

1
@gdoron Credimi, gestire le lezioni di JS e considerare la separazione è un salvavita quando hai un grande progetto
Abdul Munim


2

Di solito inserisco JS che necessita dell'accesso alle proprietà del modello, nelle funzioni e poi passo il @something nella vista. Per esempio

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

nella vista aggiungo l'invocazione della funzione tramite (solo un esempio):

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

1

Penso che tu sia bloccato a dover mettere quel codice JS nella vista. Il parser Razor, per quanto ne so, non esaminerà i file .js, quindi qualsiasi cosa tu abbia che usi @non funzionerà. Inoltre, come hai notato, a Javascript stesso non piace questo @carattere in giro senza motivo, a parte, ad esempio, in una stringa.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.