2012-06-19 10 views
46

Sto lavorando all'app Web in cui la pagina principale contiene due parti: il blocco costante che è sempre visibile e il blocco di informazioni costituito da una delle 3 viste parziali. Ognuna delle viste parziali appare come risultato della richiesta AJAX e viene caricata una sola volta (dopo che le finestre di commutazione sono fornite da jquery). Funziona bene ma ho avuto un problema.È corretto inserire JavaScript nelle viste parziali

Il codice html delle viste parziali contiene funzioni js che vengono utilizzate anche nel blocco costante e nel blocco informazioni. Quando la pagina viene caricata, queste funzioni possono "vedersi" e funziona, ma il resharper non trova le dichiarazioni delle funzioni e mi avvisa di ciò. Non riesco a risolvere il problema trasferendoli in un file js esterno a causa della sintassi del rasoio che può essere trovata nel loro codice.

Cosa posso fare con questo?

Grazie.

Aggiornamento:

Infine ho deciso di risolvere il problema che separa il mio codice js da vista. Quindi la nuova domanda era come includere la sintassi del rasoio nei file js o qual è l'alternativa accettabile. Le soluzioni popolari che ho trovato utilizzano variabili globali, attributi dei dati e quello che mi piace di più: la libreria RazorJS di John Katsiotis.

http://djsolid.net/blog/razorjs---write-razor-inside-your-javascript-files

spero che sta andando a lavoro stabile e rendere ReSharper felice.

Cheers!

Aggiornamento:

Dopo 3 anni ho ricordato questa domanda e ha deciso di aggiornarlo secondo la mia esperienza. In effetti ora preferirei non raccomandare l'uso di librerie aggiuntive per questo. Soprattutto se non sei l'unico membro del team di progetto ... È molto meglio se sei assicurato in tutte le tue librerie, sono supportate da creator e community e possono essere facilmente integrate nel tuo IDE (se usi la sintassi speciale ad esempio) . Anche tutti i ragazzi del tuo team dovrebbero essere consapevoli di come funziona. Quindi ora suggerirei di fare le seguenti cose:

  1. Tenere tutto il JS in file separati. Isolare il più possibile. Fornire l'API esterna per questo.
  2. Chiama le funzioni API dalle tue Visualizzazioni.
  3. Passa tutti gli URL generati da Razor, i messaggi di testo, le costanti come parametro di risorsa.

Ad esempio:

js di file:

$.api.someInitFunction = function(resources){ ... } 

Vista:

<script> 
    $.api.someInitFunction({ 
     urls: { myAction: '@Url.Action("MyAction", "MyController")' }, 
     messages: { error: '@errorMessage' }, 
     consts: { myConst: @myIntConst } 
    }); 
</script> 
+0

Non riuscivo a decidere cosa risposta è stata più utile per me :) – Tomy

+0

Grazie e benvenuto StackOverflow :) –

+0

È piacevole iniziare con un ricevimento così bello, molte grazie! – Tomy

risposta

27

Se ReSharper si avverte che non è un grosso problema^_^

Ma se fossi in te non metterei JavaScript in la vista parziale su tutto.

Poiché la vista parziale potrebbe essere inserita in una pagina molte volte, si avranno problemi con i propri JavaScript.

E per il tuo caso, se non è possibile separare il file JavaScript in JS, solo crea un altro PartialView e inserisci questi script e rendilo semplicemente nella tua pagina principale.

+0

Grazie, Wahid! Ma a volte i codici Resharper sono davvero migliori di me :) In effetti so che non è una buona idea mettere js in viste parziali. Ma come ho già detto, sulla mia pagina esistono in una sola copia quindi nidificare per esempio è semplicemente "impossibru". Seguendo il tuo consiglio sulla visualizzazione parziale con gli script, renderò le viste principali piuttosto buone. Ma è un peccato che RenderPartial non risolva il problema del Resharper. Posso sbagliarmi? – Tomy

+3

Se si tratta di una piccola applicazione e non si desidera dedicare più tempo a questa operazione, è sufficiente mantenere il proprio lavoro. Ma se parli di "Abitudine di programmazione", devi separare il tuo JavaScript da Views. –

+0

E per '@ Html.ActionLink (...)' ci sono molte soluzioni, ma nessuna di queste è quella di mettere il codice JavaScript direttamente in PartialView. Puoi dare un'occhiata a questa risposta http://stackoverflow.com/a/3789959/105445 –

3

Sono d'accordo con Wahid sul fatto che non si debba inserire JavaScript nelle viste parziali o meno. Ho visto abbastanza codice che fa questo per sapere che non porta a nulla di buono.

Direi anche che dovresti essere in grado di trasferire la logica incapsulata nella sintassi del rasoio in JavaScript, devi solo passare al tuo JavaScript le informazioni necessarie alla tua logica.

Sto solo indovinando per esperienza con questo prossimo commento, ma dovresti progettare il JavaScript nello stesso modo in cui avresti progettato la struttura del tuo codice C# o VB.NET. In questo modo la logica che stai usando Razor dovrebbe essere parte del tuo JavaScript.

In questo modo il tuo JavaScript sarà più facile da mantenere e presumo che anche Resharper sia più felice.

+0

Grazie per la tua risposta! Ma il problema non è con la logica. Uso Razor per creare collegamenti (ad esempio Url.Action) e cose del genere. Passandoli come parametri sembra piuttosto strano, immagino. – Tomy

+0

Per i collegamenti puoi ancora metterli su href basta usare preventDefault. Anche gli attributi di dati HTML5 sono utili in queste situazioni. controlla dojo o yui3 e guarda come vengono create le librerie. – eaglestorm

+0

Funzionalità utili, grazie! – Tomy

1

Lo faccio e lo trovo molto conveniente. Funziona bene per caricare in modo dinamico frammenti di javascript parziali con la disponibilità di ViewBag, HttpContext, ecc.

Ne risulta qualcosa che sembra utilizzare i modelli T4.

È possibile ottenere anche la convalida javascript, intellisense, ecc. Se si aggiungono tag script fantasma come questo.

@using System.Configuration 
@if (false) 
{ 
    @:<script type="text/javascript"> 
}  
     $scope.clickCartItem = function(cartItem) { 
      console.log(cartItem); 
      window.location.href [email protected]("('" + ConfigurationManager.AppSettings["baseUrl"] + "/Checkout/' + cartItem.ItemId)"); 
     }; 
     dataAccess.getCart(
     function (response) { 
      //... 
     }, 
     function (response) { 
      //... 
     } 
     ); 

@if (false) 
{ 
    @:</script> 
} 
6

Se si vuole scrivere una vista parziale che vengono incapsulati "widget" che solo il lavoro una volta che li includere in una pagina, poi incorporare un blocco di script all'interno della vista parziale è un modo pulito per avvolgere il markup e la script di inizializzazione insieme in una vista parziale. Ad esempio, potrei avere una vista parziale denominata "_EventList" che utilizzo nel mio sito. Se metto due posti nella mia pagina principale dovrebbe funzionare e preferisco non dover scrivere la logica nella mia pagina master per inizializzare il widget.

Se non lo utilizzerete più di una volta in una pagina, è semplice. Ma se puoi, allora avvolgi lo script in modo che non venga eseguito due volte. Vedi sotto. Per motivi di frammenti di overflow dello stack, lo simulo ripetendo due volte la vista parziale nello snippet di codice per rappresentare una vista parziale due volte in una pagina principale.

La mia pagina master potrebbe essere simile:

<div id="left-nav"> 
    @Html.Partial("_EventList")   
</div> 

<div id="body"> 
</div> 

<div id="right-nav"> 
    @Html.Partial("_EventList") 
</div> 

Esempio:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 

 
<!-- Self-contained partial view containing widget --> 
 

 
<div id="widgetDiv" class="panel panel-default"> 
 

 
    <div class="panel-heading">Event Dates</div> 
 
    <div class="panel panel-group"> 
 
     <ul class="widget"> 
 
     <!-- These will load dynamically --> 
 
     </ul> 
 
    </div> 
 

 
    <script> 
 
     $(document).ready(function() { 
 

 
      // Run this once only in case widget is on page more than once 
 
      if(typeof $widget == 'undefined') { 
 
       $widget = $("ul.widget"); // could be more than one 
 
       // mock data to simulate an ajax call 
 
       var data = [ 
 
        {Description: "March", StartDate: "03/01/2015"}, 
 
        {Description: "April", StartDate: "04/01/2015"}, 
 
        {Description: "May", StartDate: "05/01/2015"} 
 
       ]; 
 

 
       $.each($widget, function(w, widget) { 
 
        // might be an $.ajax call 
 
        $.each(data, function(i, row) { 
 
         $(widget).append("<li><a href='/Widget/Search?startDate=" + row.StartDate + "'>" + row.Description + "</a></li>"); 
 
        }); 
 
       }); 
 
      } 
 
     }); 
 
    </script> 
 
</div> 
 
<!-- End of widget/partial view --> 
 

 

 

 
<!-- Second copy of above for sake of example snippet --> 
 
<!-- No need to read further --> 
 

 

 

 

 

 

 

 

 

 
<!-- Self-contained partial view containing widget --> 
 

 
<div id="widgetDiv" class="panel panel-default"> 
 

 
    <div class="panel-heading">Event Dates</div> 
 
    <div class="panel panel-group"> 
 
     <ul class="tinylist nav nav-sidebar widget"> 
 
     <!-- These will load dynamically --> 
 
     </ul> 
 
    </div> 
 

 
    <script> 
 
     $(document).ready(function() { 
 

 
      // Run this once only in case widget is on page more than once 
 
      if(typeof $widget == 'undefined') { 
 
       $widget = $("ul.widget"); // could be more than one 
 
       // mock data to simulate an ajax call 
 
       var data = [ 
 
        {Description: "March", StartDate: "03/01/2015"}, 
 
        {Description: "April", StartDate: "04/01/2015"}, 
 
        {Description: "May", StartDate: "05/01/2015"} 
 
       ]; 
 

 
       $.each($widget, function(w, widget) { 
 
        // might be an $.ajax call 
 
        $.each(data, function(i, row) { 
 
         $(widget).append("<li><a href='/Widget/Search?startDate=" + row.StartDate + "'>" + row.Description + "</a></li>"); 
 
        }); 
 
       }); 
 
      } 
 
     }); 
 
    </script> 
 
</div> 
 
<!-- End of widget/partial view -->

+1

Nonostante il fatto che ci siano più risposte in aumento, raccomanderei sicuramente questo approccio piuttosto che dividere le dipendenze con alte coesione solo per il gusto di raggrupparle per estensioni. Quindi sì un grande ++ da me. –

+0

Sono assolutamente d'accordo: non dividere coesivo HTML e JS. Senza dubbio ... Ma la tua vista parziale di esempio non funzionerà per tutti i consumatori di modelli Visual Studio di ASP MVC: All'interno di '_Layout.cshtml' jQuery viene reso * dopo *' @RenderBody() 'quindi non puoi usarlo. La tua soluzione non è davvero migliore: la prima riga '' includerà jQuery due o più volte (1x per visualizzazione parziale e 1x in te '_Layout.cshtml') – Marcel

+0

@Marcel: l'esempio è pensato per funzionare all'interno dell'editor del frammento di codice al fine di mostrare la tecnica. In realtà l'ho avvertito, compreso il multiplo jQuery incluso, nella mia risposta e i miglioramenti suggeriti, quindi non sono sicuro se leggete il mio "disclaimer". Le mie vere pagine di layout di solito hanno jquery e altri script nella sezione head. Il lavoro aggiuntivo era al di fuori del tempo di applicazione/i requisiti della mia risposta al momento. Siete invitati a migliorare questa risposta purché funzioni ancora all'interno di Stack Overflow – codenheim

Problemi correlati