2012-06-19 57 views
46

Estoy trabajando en la aplicación web donde la página principal contiene dos partes: el bloque constante que siempre está visible y el bloque de información compuesto por una de las 3 vistas parciales. Cada una de las vistas parciales aparece como resultado de la solicitud AJAX y se carga una sola vez (después de que jquery proporcione las ventanas de cambio). Funciona bien pero me he enfrentado a un problema.¿Está bien poner JavaScript en vistas parciales?

El código html de vistas parciales contiene funciones js que se usan en el bloque constante y en el bloque de información también. Cuando la página está cargada, estas funciones pueden "verse" entre ellas y funciona, pero el reafilador no puede encontrar declaraciones de funciones y advertirme sobre esto. No puedo resolver el problema transfiriéndolos a un archivo js externo debido a la sintaxis de la afeitadora que se puede encontrar en su código.

¿Qué puedo hacer con esto?

Gracias.

Actualización:

Finalmente me he decidido a resolver el problema de la separación de mi código js desde puntos de vista. Entonces, la nueva pregunta fue cómo incluir la sintaxis de la afeitadora en archivos js o cuál es la alternativa aceptable. Las soluciones populares que he encontrado están usando variables globales, atributos de datos y el que más me gusta: la biblioteca RazorJS de John Katsiotis.

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

espero que va a trabajar y hacer estable ReSharper feliz.

¡Salud!

Actualización:

Después de 3 años recordé esta cuestión y decidió actualizarlo de acuerdo a mi experiencia. De hecho, ahora prefiero no recomendar el uso de bibliotecas adicionales para eso. Especialmente si usted no es el único miembro del equipo del proyecto ... Es mucho mejor si está asegurado en todas sus bibliotecas, es compatible con el creador y la comunidad y puede integrarse fácilmente en su IDE (si utiliza una sintaxis especial, por ejemplo) . Además, todos los chicos de tu equipo deberían saber cómo funciona. Así que ahora sugeriría hacer lo siguiente:

  1. Mantenga todos los archivos JS en archivos separados. Aísla todo lo que puedas. Proporcione la API externa para ello.
  2. Llamar a las funciones API desde sus Vistas.
  3. Pase todos los URL generados por Razor, mensajes de texto, constantes como parámetro de recurso.

Por ejemplo:

js archivo:

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

Vista:

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

no podía decidir qué respuesta era más útil para mí :) – Tomy

+0

Gracias y bienvenidos a Stackoverflow :) –

+0

Es agradable comenzar con una recepción tan agradable, muchas gracias! – Tomy

Respuesta

27

Si ReSharper le advierte que no es un gran problema^_^

Pero Si yo fuera tú, no pondría JavaScript en la vista parcial en absoluto.

Dado que la vista parcial podría insertarse varias veces en una página, se producirá un problema con los JavaScripts.

Y para su caso, si no pudo separar el archivo JavaScript a JS, entonces solo cree otra PartialView y coloque estos scripts en ella y simplemente grábela en su página principal.

+0

¡Gracias, Wahid! Pero a veces los códigos Resharper son mejores que yo :) De hecho, sé que no es una buena idea poner js en vistas parciales. Pero como ya he dicho, en mi página existen en una copia, por lo que anidar, por ejemplo, es simplemente "impossibru". Siguiendo sus consejos sobre vistas parciales con scripts, voy a hacer que las vistas principales sean bastante buenas. Pero es una lástima que RenderPartial no resuelva el problema de Resharper. ¿Puedo estar equivocado? – Tomy

+3

Si se trata de una aplicación pequeña y no desea dedicarle más tiempo, simplemente conserve su trabajo como tal. Pero si estás hablando del "hábito de programación", entonces debes separar tu JavaScript de Vistas. –

+0

Y para el '@ Html.ActionLink (...)' hay muchas soluciones, pero ninguna de ellas es poner el JavaScript directamente en PartialView. Puede ver esta respuesta http://stackoverflow.com/a/3789959/105445 –

3

Estoy de acuerdo con Wahid en que no debe poner JavaScript en las vistas de ninguna manera parcial o de lo contrario. He visto suficiente código que hace esto para saber que solo conduce a nada bueno.

También diría que debe poder transferir la lógica encapsulada en la sintaxis de Razor al JavaScript, solo tiene que pasar a su JavaScript la información que necesita su lógica.

Estoy adivinando por experiencia con este próximo comentario, pero debe diseñar el JavaScript de la misma manera que diseñaría la estructura de su código C# o VB.NET. De esa manera, la lógica para la que está usando Razor debe ser parte de su JavaScript.

De esta manera, su JavaScript será más fácil de mantener y supongo que Resharper también debería ser más feliz.

+0

Gracias por su respuesta! Pero el problema no está en la lógica. Yo uso Razor para construir enlaces (Url.Action por ejemplo) y cosas por el estilo. Pasarlos como parámetros parece bastante extraño, supongo. – Tomy

+0

Para enlaces aún puede ponerlos en el href simplemente use preventDefault. También los atributos de datos html5 también son útiles en estas situaciones. echa un vistazo a dojo o yui3 y ver cómo se construyen las bibliotecas. – eaglestorm

+0

¡Funciones útiles, gracias! – Tomy

1

Lo hago y lo encuentro muy conveniente. Funciona bien cargar dinámicamente fragmentos de JavaScript parciales con la disponibilidad de ViewBag, HttpContext, etc.

Resulta en algo que se siente como usar plantillas T4.

Incluso puede obtener la validación de JavaScript, intellisense, etc. si agrega etiquetas de script phantom como esta.

@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

Si desea escribir vistas parciales que están encapsulados "widgets" que solo funcionan una vez que los incluye en una página, a continuación, la incorporación de un bloque de script dentro de la vista parcial es una forma limpia para envolver el margen de beneficio y la script de inicialización juntos en una vista parcial. Por ejemplo, podría tener una vista parcial llamada "_EventList" que utilizo en mi sitio. Si coloco en dos lugares en mi página maestra, debería funcionar y prefiero no tener que escribir lógica en mi página maestra para inicializar el widget.

Si nunca lo usará más de una vez en una página, es simple. Pero si es posible, envuelva la secuencia de comandos para que no se ejecute dos veces. Vea abajo. Por el bien de los fragmentos de Stack Overflow lo simulo repitiendo la vista parcial dos veces en el fragmento de código para representar una vista parcial dos veces en una página maestra.

Mi página maestra podría ser:

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

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

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

Ejemplo:

<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

A pesar del hecho de que hay más respuestas subidas de tono, definitivamente recomendaría este enfoque en lugar de dividir las grandes dependencias cohesivas solo por el hecho de agruparlas por extensiones. Así que sí, un gran ++ de mí. –

+0

Estoy totalmente de acuerdo: no separe HTML y JS coherentes. Sin duda ... Pero su vista parcial de ejemplo no funcionará para todos los consumidores de las plantillas Visual Studio de ASP MVC: Inside '_Layout.cshtml' jQuery se representa * después de' '@RenderBody()' por lo que no puede usarlo. Su solución no es realmente mejor: la primera línea '' incluirá jQuery dos o más veces (1x por vista parcial y 1x en usted '_Layout.cshtml') – Marcel

+0

@Marcel: el ejemplo está destinado a funcionar dentro del editor de fragmentos de código para mostrar la técnica. De hecho, lo advertí, incluidos los múltiples jquery incluidos, en mi respuesta y las mejoras sugeridas, por lo que no estoy seguro de si leyó mi "exención de responsabilidad". Mis páginas de diseño reales generalmente tienen jquery y otras secuencias de comandos en la sección de la cabeza. El trabajo adicional estaba fuera del alcance/requisito de tiempo de mi respuesta en ese momento. Le invitamos a mejorar esta respuesta siempre que funcione dentro de Stack Overflow – codenheim

Cuestiones relacionadas