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

Vue标签切换时如何保留表单输入与下拉选择数据?

Vue标签页切换表单数据丢失问题解决

我正在学习Vue,现有一个包含两个标签页的Tab组件,标签页内设有输入框和下拉选择器。切换标签页时,下拉选中项、输入框文本等数据会丢失,已尝试使用v-model但无效果,请求技术帮助。

相关代码

标签页视图代码

<script setup>
import { ref } from 'vue';

const nestedRouteItems = ref([
    {
        label: 'Personal',
        to: '/uikit/ficha'
    },
    {
        label: 'Seat',
        to: '/uikit/ficha/seat'
    },
]);

</script>

<template>
    <div class="grid">
        <div class="col-12 md:col-12">
            <div class="card p-fluid">
                <h5>Ficha</h5>
                <div class="col-12 md:col-12">
                    <div class="card card-w-title">
                        <h5>Tab container</h5>
                        <p>Lorem ipsum dolor sit amet, consectetur.</p>
                        <TabMenu :model="nestedRouteItems" />
                        <router-view />
                    </div>
                </div>
                
            </div>
        </div>
    </div>
</template>

第一个标签页内容代码

<template>
    <div class="flex align-items-center py-5 px-3">
        <div class="card p-fluid" style="width:800px">
                <h5>Datos personales</h5>
                <div class="field">
                    <label for="name1">Nombre</label>
                    <InputText id="name1" type="text" />
                </div>
            </div>
    </div>
</template>

第二个标签页内容代码

<script setup>
import { ref } from 'vue';

const dropdownItems = ref([
    { name: 'Principal', code: 'Principal' },
    { name: 'Laboral', code: 'Laboral' },
    { name: 'Familiar', code: 'Familiar' }
]);

const dropdownItem = ref(null);

</script>
<template>
    <div class="flex align-items-center py-5 px-3">
        <div class="card p-fluid" style="width:800px">
            <h5>Domicilio</h5>
            <div class="field">
                <label for="tipoDomicilio">Tipo de domicilio</label>
                <Dropdown id="tipoDomicilio" v-model="dropdownItem" :options="dropdownItems" optionLabel="name" placeholder="Elegir opción..."></Dropdown>
            </div>
        </div>
    </div>
</template>

问题原因

切换标签页时,<router-view>对应的路由组件会被销毁,再次切换回来时组件重新创建,导致组件内部的ref数据重置。v-model仅绑定组件内部数据,组件销毁后数据自然丢失。

解决方案

方案1:用keep-alive缓存路由组件(最简单)

在<router-view>外层包裹<keep-alive>,让组件切换时不被销毁,保留内部状态:

<template>
    <div class="grid">
        <div class="col-12 md:col-12">
            <div class="card p-fluid">
                <h5>Ficha</h5>
                <div class="col-12 md:col-12">
                    <div class="card card-w-title">
                        <h5>Tab container</h5>
                        <p>Lorem ipsum dolor sit amet, consectetur.</p>
                        <TabMenu :model="nestedRouteItems" />
                        <!-- 缓存路由组件 -->
                        <keep-alive>
                            <router-view />
                        </keep-alive>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

方案2:将数据提升到父组件管理(适合需要共享数据的场景)

把表单数据定义在标签页视图组件(父组件)中,通过props传递给子路由组件,子组件绑定父组件的变量,这样组件销毁重建时数据不会丢失:

修改标签页视图组件

<script setup>
import { ref } from 'vue';

const nestedRouteItems = ref([
    {
        label: 'Personal',
        to: '/uikit/ficha'
    },
    {
        label: 'Seat',
        to: '/uikit/ficha/seat'
    },
]);

// 父组件定义共享表单数据
const personalForm = ref({
    name: ''
});

const seatForm = ref({
    dropdownItem: null
});
</script>

<template>
    <div class="grid">
        <div class="col-12 md:col-12">
            <div class="card p-fluid">
                <h5>Ficha</h5>
                <div class="col-12 md:col-12">
                    <div class="card card-w-title">
                        <h5>Tab container</h5>
                        <p>Lorem ipsum dolor sit amet, consectetur.</p>
                        <TabMenu :model="nestedRouteItems" />
                        <!-- 传递数据给子组件 -->
                        <router-view 
                            :personal-form="personalForm"
                            :seat-form="seatForm"
                        />
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

修改第一个标签页组件

<script setup>
// 接收父组件传递的props
const props = defineProps({
    personalForm: {
        type: Object,
        required: true
    }
});
</script>

<template>
    <div class="flex align-items-center py-5 px-3">
        <div class="card p-fluid" style="width:800px">
                <h5>Datos personales</h5>
                <div class="field">
                    <label for="name1">Nombre</label>
                    <InputText id="name1" type="text" v-model="personalForm.name" />
                </div>
            </div>
    </div>
</template>

修改第二个标签页组件

<script setup>
import { ref } from 'vue';

const dropdownItems = ref([
    { name: 'Principal', code: 'Principal' },
    { name: 'Laboral', code: 'Laboral' },
    { name: 'Familiar', code: 'Familiar' }
]);

// 接收父组件传递的props
const props = defineProps({
    seatForm: {
        type: Object,
        required: true
    }
});
</script>
<template>
    <div class="flex align-items-center py-5 px-3">
        <div class="card p-fluid" style="width:800px">
            <h5>Domicilio</h5>
            <div class="field">
                <label for="tipoDomicilio">Tipo de domicilio</label>
                <Dropdown id="tipoDomicilio" v-model="seatForm.dropdownItem" :options="dropdownItems" optionLabel="name" placeholder="Elegir opción..."></Dropdown>
            </div>
        </div>
    </div>
</template>

方案3:使用状态管理工具(适合复杂场景)

如果项目中存在多处共享表单数据的需求,可以使用Vuex或Pinia来管理全局状态,将表单数据存入全局仓库,组件从仓库获取和更新数据,确保切换标签页时数据不丢失。


内容的提问来源于stack exchange,提问作者Pablo Neutrino Insaurralde

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 22:45:39