Estoy tratando de crear una extensión de aplicación de tema para Shopify para ejecutar JavaScript cuando se hace clic en el botón Agregar al carrito. Como ejemplo:
<head> <script type="text/javascript" src={{ 'jquery-3.6.0.js' | asset_url }} defer></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js" rel="preload" defer="defer"></script> </head> ... <button id="add-btn">click me!</button> <script> jQuery( document ).ready(function() { $('#add-btn').on('click', function(event){ alert("clicked") }) }); </script>Esto está dentro de una extensión de aplicación de hoja en la carpeta de bloques.
Parece que jquery no se carga y aparece un error
Uncaught ReferenceError: jQuery is not defined¿Alguna idea de por qué?
Resumen: está cargando la biblioteca jQuery con la palabra clave defer para que no bloquee la carga de la página, pero está haciendo referencia a jQuery antes de que la página termine de cargarse.
Al cargar jQuery usando el atributo defer en la etiqueta del script, el navegador comenzará a cargar el script inmediatamente, pero no lo ejecutará hasta que se haya cargado el contenido del DOM:
<script type="text/javascript" src={{ 'jquery-3.6.0.js' | asset_url }} defer></script>Sin embargo, la etiqueta de secuencia de comandos en línea más abajo en la página se ejecutará inmediatamente cuando el navegador llegue a ella:
<script> jQuery( document ).ready(function() { // ERROR! jQuery library hasn't been run yet, so we can't use jQuery to select the document! $('#add-btn').on('click', function(event){ alert("clicked") }) }); </script> Dado que los scripts diferidos se ejecutan en el orden en que se definen, su instinto podría ser intentar poner la palabra clave defer en la etiqueta del script en línea, pero desafortunadamente, defer y async solo se aplican a los archivos de script externos.
Hay varias formas de resolver este problema de tiempo. Dos posibilidades son:
Si crea un archivo JS externo, puede cargar el script con la palabra clave defer ya que todos los scripts diferidos se ejecutan en el orden en que fueron llamados una vez que el DOM está listo. Como una ventaja adicional, no necesitaría envolver su función con jQuery(document).ready , ya que sabría que el documento está listo cuando se ejecuta el script.
Si la etiqueta de secuencia de comandos en línea tiene sentido, el uso de Javascript estándar para configurar su evento resolverá su problema. El código equivalente sería usar la función addEventListener para escuchar el evento DOMContentLoaded :
<script> // This event is created before the DOM is loaded, so jQuery doesn't exist yet document.addEventListener('DOMContentLoaded', function() { // This event will be run after the deferred scripts above, so jQuery exists now $('#add-btn').on('click', function(event){ alert("clicked") }) }); </script>