You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js能否使用单个v-for循环向两个不同div渲染元素

需求目标

需要实现的DOM输出结构如下:

<div id="tabs">
    <div id="first">
        <a>tab 1</a>
        <a>tab 2</a>
    </div>
    <div id="second">
        <a>tab 3</a>
    </div>
</div>
现有实现的问题

硬编码双循环方案

目前的实现是写死两个分组容器,分别用v-for渲染对应分组下的tab,代码如下:

// tabs.js
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>
    `
}

这个写法性能没问题,但可维护性差:后续新增、删除分组时,既要改data里的数据结构,还要同步改模板里的DOM结构,很容易漏改。

嵌套循环加v-if的构思方案

之前尝试过把所有tab存成一个平级数组,用category字段标记所属分组,外层循环生成分组容器,内层循环全量遍历所有tab,用v-if判断tab是否属于当前分组再渲染,代码如下:

// tabs.js
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>
    `
}

这个写法不需要硬编码多个分组容器,但性能很差:有几个分组就要把全量tab从头到尾遍历几遍,存在大量无效判断,tab数量多的时候性能损耗非常明显。

优化实现方案

直接用Vuev-for遍历对象的语法,遍历你已经按分组装好的tabs对象即可,同时拿到分组ID和对应分组下的tab列表,不需要硬编码模板,也没有冗余遍历:

// tabs.js
export default {
    data() {
        return {
          tabs: {
              first: [{ name: 'tab1' }, { name: 'tab2' }],
              second: [{ name: 'tab3' }],
          }
        }
    },
    template: `
        <div id="tabs">
            <div :id="categoryId" v-for="(tabList, categoryId) in tabs" :key="categoryId">
                <a v-for="tab in tabList" :key="tab.name">{{ tab.name }}</a>
            </div>
        </div>
    `
}

这个方案的优势:

  • 性能和硬编码双循环完全一致:总遍历次数等于tab总数量,没有任何冗余迭代
  • 维护成本低:后续新增、删除、修改分组,只需要调整data里的tabs对象,不需要动模板代码
  • 输出的DOM结构和需求要求的完全一致,没有多余属性或节点

如果你的源数据是带category字段的平级数组,可以先用计算属性做一次分组预处理,只在源数据变化时重新计算分组结果,渲染时直接遍历分组后的对象即可,同样不会有嵌套循环的性能问题:

// tabs.js
export default {
    data() {
        return {
          rawTabs: [
              { name: 'tab1', category: 'first' },
              { name: 'tab2', category: 'first' }, 
              { name: 'tab3', category: 'second' }
          ]
        }
    },
    computed: {
        groupedTabs() {
            return this.rawTabs.reduce((res, tab) => {
                const cat = tab.category;
                if (!res[cat]) res[cat] = [];
                res[cat].push(tab);
                return res;
            }, {})
        }
    },
    template: `
        <div id="tabs">
            <div :id="categoryId" v-for="(tabList, categoryId) in groupedTabs" :key="categoryId">
                <a v-for="tab in tabList" :key="tab.name">{{ tab.name }}</a>
            </div>
        </div>
    `
}

内容的提问来源于stack exchange,提问作者exec1990

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 23:18:49