方案一:使用一个页面,通过切换三个组件展示每一步
- 新建三个组件,引入主页面
- 点击下一步,传递给父组件 form 对象和当前索引
- 父组件存储子组件传递过来的数据,并且根据索引存储成数组的形式,并且根据索引控制组件的显示与卸载
- 点击上一步时,传递给父组件索引,父组件切租架子那显示
- 使用
<keep-alive>
缓存各个组件的表单数据,不用考虑返回数据消失的问题 - 组件缓存之后,在组件内只有第一次加载执行 onMounted,之后 通过 onActivated、onDeactivated监听组件的渲染和卸载
login1.vue
<template>
<div>
<label>姓名:<input type="text" v-model="form.name"></label>
<label>密码:<input type="text" v-model="form.pwd"></label>
<button @click="next">下一步</button>
</div>
</template>
<script setup lang="ts">
let form = reactive({
name: '',
pwd: ''
})
// 传递参数
const emit = defineEmits(["change"]); // 所有方法一起定义
const next = () => {
emit("change", form, 0);
};
onActivated(() => {
console.log("onActivated")
});
onDeactivated(() => {
console.log("onDeactivated")
});
onMounted(() => {
console.log("onMounted")
});
onUnmounted(() => {
console.log("onUnmounted")
});
</script>
<style lang="scss" scoped>
</style>
login2.vue
<template>
<div>
<label>地址:<input type="text" v-model="form.address"></label>
<label>爱好:<input type="text" v-model="form.hobby"></label>
<button @click="back">上一步</button>
<button @click="next">下一步</button>
</div>
</template>
<script setup lang="ts">
let form = reactive({
address: '',
hobby: ''
})
// 传递参数
const emit = defineEmits(["change", "back"]); // 所有方法一起定义
const next = () => {
emit("change", form, 1);
};
const back = () => {
emit("back", 1);
}
onActivated(() => {
console.log("onActivated")
});
onDeactivated(() => {
console.log("onDeactivated")
});
onMounted(() => {
console.log("onMounted")
});
onUnmounted(() => {
console.log("onUnmounted")
});
</script>
<style lang="scss" scoped>
</style>
login3.vue
<template>
<div>
<label>电话:<input type="text" v-model="form.tel"></label>
<label>验证码:<input type="text" v-model="form.code"></label>
<button @click="back">上一步</button>
<button @click="next">提交</button>
</div>
</template>
<script setup lang="ts">
let form = reactive({
tel: '',
code: ''
})
// 传递参数
// 传递参数
const emit = defineEmits(["change", "back"]); // 所有方法一起定义
const next = () => {
emit("change", form, 2);
};
const back = () => {
emit("back", 2);
}
onActivated(() => {
console.log("onActivated")
});
onDeactivated(() => {
console.log("onDeactivated")
});
onMounted(() => {
console.log("onMounted")
});
onUnmounted(() => {
console.log("onUnmounted")
});
</script>
<style lang="scss" scoped>
</style>
父组件login.vue
<template>
<keep-alive>
<login1 @change="change" @back="back" v-if="flag == 0"></login1>
<login2 @change="change" @back="back" v-else-if="flag == 1"></login2>
<login3 @change="change" @back="back" v-else></login3>
</keep-alive>
</template>
<script setup lang="ts">
import login1 from "../../components/login1.vue"
import login2 from "../../components/login2.vue"
import login3 from "../../components/login3.vue"
let flag = ref(0)
let form = reactive([])
const change = (data: object, num: number) => {
form[num] = data
flag.value = num + 1
if (num == 2) {
let form1 = Object.assign(form[0], form[1], form[2])
// 提交的对象{address: "2",code: "3",hobby: "2",name: "1",pwd: "1",tel: "3"}
console.log(form1)
}
}
const back = (num: number) => {
flag.value = num - 1
}
</script>
<style lang="scss" scoped>
</style>
方案二:每一步为一个页面,缓存页面
- vue2.x配置
<template>
<keep-alive>
<router-view v-if="$route.meta.keepAlive" />
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"/>
</template>
- vue3.0配置
<template>
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" v-if="$route.meta.keepAlive"/>
</keep-alive>
<component :is="Component" v-if="!$route.meta.keepAlive"/>
</router-view>
</template>