Tengo un objeto que recorro con cada bloque. Cuando paso el mouse, cambio temporalmente una propiedad en la entrada del objeto real y la uso para asignar una clase. Esto funciona bien, pero también provoca que se active innecesariamente otra reactividad.
<script> let things = [ { id: 1, name: 'apple' }, { id: 2, name: 'banana' }, { id: 3, name: 'carrot' }, { id: 4, name: 'doughnut' }, { id: 5, name: 'egg' }, ]; function makePretty(somethings) { const prettyThings = somethings.map(thing => thing.name).join(' '); console.log(prettyThings); return prettyThings; } $: prettyThings = makePretty(things) </script> <ul> {#each things as thing (thing.id)} <li class:hover={thing.hover} on:mouseenter={() => (thing.hover = true)} on:mouseleave={() => (thing.hover = false)} > {thing.name} </li> {/each} </ul> <style> .hover { background-color: cyan; } </style>REPL: https://svelte.dev/repl/c658cccd0bc2471a8f9c4758387340c5?version=3.48.0 En la consola, puede ver con qué frecuencia se activa la reactividad en las cosas bonitas cuando se mueve sobre la lista con el mouse.
Me doy cuenta de que este es el comportamiento esperado, ya que el objeto 'cosas' se cambia efectivamente en cada mouseenter y mouseleave. Y así se llama a las cosas bonitas cada vez.
¿Cuál sería una forma ideomática de aplicar un desplazamiento a una 'fila' de una matriz de objetos, sin cambiar el objeto en sí? Al hacerlo, el objeto aún debe ser modificable en vivo por otras operaciones (por ejemplo, agregar, eliminar, ...).
Una forma de hacer esto sería dividir el renderizado en un componente separado.
<script> export let thing; </script> <li class:hover={thing.hover} on:mouseenter={() => (thing.hover = true)} on:mouseleave={() => (thing.hover = false)} > {thing.name} </li> <style> .hover { background-color: cyan; } </style> {#each things as thing (thing.id)} <ItemDisplay {thing} /> {/each}Sin embargo, tal vez haya mejores enfoques.
EDITAR: puede almacenar la "Fila Hovered" en una variable separada, luego aplicar el estilo basado en "HoveredRowId === thing.id"
<script> let things = [ { id: 1, name: 'apple' }, { id: 2, name: 'banana' }, { id: 3, name: 'carrot' }, { id: 4, name: 'doughnut' }, { id: 5, name: 'egg' }, ]; let hoveredId = 0; function makePretty(somethings) { const prettyThings = somethings.map(thing => thing.name).join(' '); console.log(prettyThings); return prettyThings; } $: prettyThings = makePretty(things) </script> <ul> {#each things as thing (thing.id)} <li class:hover={thing.id === hoveredId} on:mouseenter={() => (hoveredId = thing.id)} on:mouseleave={() => (hoveredId = 0)} > {thing.name} </li> {/each} </ul> <p> Hovered ID: {hoveredId} </p> <style> .hover { background-color: cyan; } </style>REPL: https://svelte.dev/repl/e157abc957874228983c9eafb2246aa3?version=3.48.0