Tengo la siguiente estructura html
<body data-page="first"> <div class="start">Test</div> </body>y los siguientes js
$('body[data-page="first"] .start').on('click',function (){ body.attr('data-page','second'); }); $('body[data-page="second"] .start').on('click',function (){ console.log('Test'); });Esperaría que después del segundo clic en .start, la consola muestre "Prueba", pero no...
¿Puedes decirme qué estoy haciendo mal?
¡Gracias por adelantado!
El problema es que la página se procesa con la página de datos configurada en primer lugar, y cuando vuelve a hacer clic en ella, esa parte de javascript todavía ve "primero", ya que no se vuelve a procesar, por lo que necesita una función dinámica, la lectura todo la interacción con ese botón, y luego verifique qué valor tiene ese atributo. Así puedes hacer infinitos casos, y aún continuar.
$('body .start').on('click',function (){ const attr = $('body').attr('data-page'); if(attr === 'first') { $('body').attr('data-page','second'); } else { console.log('second'); } }); <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <body data-page="first"> <div class="start">Test</div> </body>Y si no te gusta el hecho de que apunta a todo el "cuerpo", lo cual es extraño, porque deberías tener solo 1 cuerpo, puedes usar una identificación para apuntar al correcto.
PD: nunca es una buena idea duplicar su función, si puede configurar todo en una función dinámica, que lee todo, es más fácil de depurar en la función y es más liviana y limpia para trabajar
$('body[data-page="first"] .start').click(function (){ var body = $('body[data-page="first"] .start'); body.attr('data-page','second'); });Si bien tiene su respuesta, no creo que se haya hecho el punto esencial en ninguna de las respuestas hasta ahora, y es que el enlace de un controlador de eventos debe ocurrir después de que exista el elemento de destino.
Cuando intenta vincular un controlador de eventos a un elemento particular en el DOM, el elemento debe existir en ese momento. Si no existe, el controlador no tiene nada a lo que vincularse y, por lo tanto, la vinculación falla. Si luego crea el elemento, es demasiado tarde, a menos que vuelva a ejecutar la declaración de vinculación.
Pronto se convertirá en una segunda naturaleza llamar a las declaraciones de enlace del controlador de eventos apropiados después de crear un nuevo elemento (modificando el HTML usando javascript) que necesita un controlador.
Por ejemplo, en mi proyecto actual hago regularmente llamadas AJAX a un servidor para reemplazar bloques de HTML a medida que suceden cosas en la página. Incluso si algunos de los elementos nuevos son exactamente iguales a los que se reemplazan, no heredarán ningún enlace de los elementos reemplazados. Cada vez que actualizo el HTML, llamo a una función que contiene las declaraciones necesarias para vincular mis controladores de eventos a la nueva copia de los elementos activos.
Su código funcionaría si hiciera el siguiente cambio:
$('body[data-page="first"] .start').on('click',function () { body.attr('data-page','second'); $('body[data-page="second"] .start').on('click',function (){ console.log('Test'); }); })Un par de otros puntos (fuera de tema, pero relacionados):
Es posible vincular un controlador a un elemento varias veces. El truco para evitar esto es incluir el método .off () en la cadena antes de vincular (sin embargo, tenga en cuenta que .off ("clic") desvinculará todos los controladores de clic vinculados a ese elemento, no solo el suyo), por ejemplo.
$("#mybutton").off("click").click(function(){myHandler()});
"la función de flecha no tiene su propio valor 'esto'" (), así que no use funciones de flecha en los controladores de eventos si planea hacer referencia a cualquiera de las propiedades del elemento a través de 'esto'. p.ej
$("#mybutton").off("clic").click(() => {console.log( ${this.id} )}); // >> "indefinido"