El objetivo es hacer que la salida se vea así:
<div id="tabs"> <div id="first"> <a>tab 1</a> <a>tab 2</a> </div> <div id="second"> <a>tab 3</a> </div> </div>Actualmente estoy usando esta solución (usando dos bucles v-for):
tabs.js (actual)
export default { data() { return { tabs: { first: [{ name: 'tab1' }, { name: 'tab2' }], second: [{ name: 'tab3' }], } } } template: ` <div id="tabs"> <div id="first"> <a v-for="tab in tabs.first">{{ tab.name }}</a> </div> <div id="second"> <a v-for="tab in tabs.second">{{ tab.name }}</a> </div> </div> ` }Tuve la idea de hacer algo como esto, pero realiza más iteraciones que en el caso de dos bucles:
tabs.js (idea)
export default { data() { return { tabs: { test: [ { name: 'tab1', category: 'first' }, { name: 'tab2', category: 'first' }, { name: 'tab3', category: 'second' } ] } } } template: ` <div id="tabs"> <div v-for='category in ["first", "second"]' :id='category' :key='category'> <template v-for="tab in tabs.test"> <a v-if="tab.category === category">{{ tab.name }}</a> </template> </div> </div> ` }Leí este tema pero contiene soluciones ligeramente diferentes, que desafortunadamente no funcionaron en este caso.
No vi ningún daño en el uso de dos v-for (uno para las claves de objeto y otro para los elementos de la matriz) en la medida en que todo es dinámico. Puede probar esta solución usando Object.keys() :
new Vue({ el: '#app', data: { tabs: { first: [{ name: 'tab1' }, { name: 'tab2' }], second: [{ name: 'tab3' }], } } }) <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <div id="tabs"> <div v-for="tab in Object.keys(tabs)" :key="tab" :id="tab"> <a v-for="tab in tabs[tab]">{{ tab.name }}</a> </div> </div> </div>No hay problema en usar más de un bucle v-for . Y no hay problema al usar bucles v-for anidados.
El problema que veo con su código actual es que no es escalable. Está codificando los valores exactos de sus pestañas en <template /> (por ejemplo: first , second ).
La idea principal aquí es recorrer las pestañas y, dentro de cada pestaña, recorrer cada contenido, sin que la <template> necesite saber cuál es la pestaña o cuántas hay.
Para que cuando cambies tus pestañas a, digamos...
{ tab1: [{ name: 'intro'}], tab2: [{ name: 'tab2-1' }, { name: 'tab2-2' }], tab3: [{ name: 'tab3' }] }la plantilla todavía funciona, sin necesidad de ningún cambio.
Para lograr este tipo de flexibilidad, debe usar un bucle v-for anidado:
<div id="tabs"> <div v-for="(items, name) in tabs" :key="name" :id="name"> <a v-for="(item, key) in items" :key="key" v-text="item.name"></a> </div> </div>Manifestación:
new Vue({ el: '#app', data: () => ({ tabs: { tab1: [{ name: 'intro' }], tab2: [{ name: 'tab2-1' }, { name: 'tab2-2' }], tab3: [{ name: 'tab3' }] } }) }) #tabs a { padding: 3px 7px } <script src="https://v2.vuejs.org/js/vue.min.js"></script> <div id="app"> <div id="tabs"> <div v-for="(links, name) in tabs" :key="name" :id="name"> <a v-for="(link, key) in links" :key="key" :href="`#${link.name}`" v-text="link.name"></a> </div> </div> </div> Pero lo llevaría un paso más allá y cambiaría las tabs para que fueran una matriz:
data: () => ({ tabs: [ [{ name: 'intro'}], [{ name: 'tab1' }, { name: 'tab2' }], [{ name: 'tab3' }] ] }) Y use :id="'tab-' + name" en las divisiones de pestañas si realmente necesita esas identificaciones únicas. (Pista: no).
Tiene más sentido para mí.
Puede agregar una propiedad calculada como .concat de ambos y hacer un bucle para ello
export default { data() { tabs: { first: [{ name: 'tab1' }, { name: 'tab2' }], second: [{ name: 'tab3' }], } }, computed: { tabsCombined () { return this.tabs.first.concat(this.tabs.second) } }, template: ` <div id="tabs"> <div v-for='category in tabsCombined' :id='category' :key='category'> <template v-for="tab in tabs.test"> <a v-if='tab.category === category>{{ tab.name }}</a> </template> </div> </div> ` }