En un componente de VueJS, quiero representar los datos que recibo de una API estructurada como se muestra a continuación (matriz de objetos).
const data = [ { "firstName": "Nick", "lastName": "Pappas", "photo": "https://via.placeholder.com/150", }, { "firstName": "John", "lastName": "Stamos", "photo": "https://via.placeholder.com/150", }, { "firstName": "George", "lastName": "Papadopoulos", "photo": "https://via.placeholder.com/150", } ]Mi objetivo es producir un diseño de "tabla de aspecto" con el requisito importante: cada objeto no es una fila, es una columna.
<script src="https://cdn.tailwindcss.com"></script> <div class="table"> <div class="photos table-row"> <div class="table-cell p-3"> photo1 </div> <div class="table-cell p-3"> photo2 </div> <div class="table-cell p-3"> photo3 </div> </div> <div class="first-names table-row"> <div class="table-cell p-3"> George </div> <div class="table-cell p-3"> Nick </div> <div class="table-cell p-3"> John </div> </div> </table>¿Cómo se podría generar algo similar a lo anterior al usar las directivas de plantilla de Vue? Mis sugerencias son:
const groupedByKey = { "firstNames": ["Nick", "John", "George"], "lastNames": ["Pappas", "Stamos", "Papadopoulos"] "photos": ["...."] }flex-direction: column en cada contenedor de la empresa. (El problema con esto es que carece de todas las propiedades de la tabla con respecto al tamaño automático de los elementos según el contenido de otros elementos de la fila).Por supuesto, esto podría lograrse al tener un ciclo separado para cada propiedad, pero por razones de rendimiento y mantenimiento, esto es algo que deseo evitar.
Votaré y aceptaré respuestas que proporcionen métodos lodash para agrupar los datos por clave como se muestra en el recorte, pero idealmente si es posible una forma única de CSS/HTML (por supuesto, usando las directivas de plantilla de Vue tanto como sea posible), sería preferible .
Combine todos los objetos en un solo objeto al distribuir la matriz en _.mergeWith() y concatenar los valores mediante la función de personalización:
const groupByKey = arr => _.mergeWith({}, ...arr, ( a = [], b = []) => a.concat(b) ) const data = [{"firstName":"Nick","lastName":"Pappas","photo":"https://via.placeholder.com/150"},{"firstName":"John","lastName":"Stamos","photo":"https://via.placeholder.com/150"},{"firstName":"George","lastName":"Papadopoulos","photo":"https://via.placeholder.com/150"}] const result = groupByKey(data) console.log(result) <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> Con Vanilla JS puede reducir la matriz a un objeto. En cada iteración, ejecute el objeto actual ( o ) a través Object.entries() , y luego itere las entradas con Array.forEach() y agréguelas a la matriz relevante. Puede usar la asignación lógica nula (??=) para iniciar claves que aún no existen.
const groupByKey = arr => arr.reduce((acc, o) => { Object.entries(o) .forEach(([k, v]) => { (acc[k] ??= []).push(v) }) return acc }, {}) const data = [{"firstName":"Nick","lastName":"Pappas","photo":"https://via.placeholder.com/150"},{"firstName":"John","lastName":"Stamos","photo":"https://via.placeholder.com/150"},{"firstName":"George","lastName":"Papadopoulos","photo":"https://via.placeholder.com/150"}] const result = groupByKey(data) console.log(result)Flexbox es una solución viable aquí, a pesar de su preocupación por los problemas de tamaño automático. (Siéntase libre de señalar esos problemas en mi demostración a continuación)
Puede representar la lista de datos con v-for , donde cada iteración es una columna:
<template> <div class="user-table"> <div class="user-column" v-for="col in data"> <img class="photo" :src="col.photo" :alt="col.firstName"> <div class="first-name">{{ col.firstName }}</div> </div> </div> </template> Luego use Flexbox para .user-table y .user-column :
.user-table { display: flex; justify-content: space-around; } .user-column { display: flex; flex-direction: column; }