超长表单分页校验,下一页和上一页功能

父组件(最外层)

javascript 复制代码
<template>
    <xx-layout title="练习">
        <div
            slot="content"
            class="hierarchy-tag-main"
        >
            <el-steps
                :space="200"
                :active="currentComponentIndex + 1"
                align-center
                style="margin-bottom: 30px;"
            >
                <el-step
                    v-for="stepItem in steps"
                    :key="stepItem.compId"
                    :status="stepItem.status"
                    :title="stepItem.label"
                />
            </el-steps>
            <div>
                <keep-alive>
                    <component
                        :is="currentComponent"
                        :ref="currentComponent"
                        :entire-data="entireData"
                    />
                </keep-alive>
            </div>
            <div class="footer">
                <el-button
                    type="default"
                    @click="save"
                >
                    暂存
                </el-button>
                <el-button
                    type="primary"
                    :disabled="currentComponentIndex <= 0"
                    @click="pre"
                >
                    上一步
                </el-button>
                <!-- 最后一步时按钮隐藏 -->
                <el-button
                    v-if="currentComponentIndex < (steps.length-1)"
                    type="primary"
                    :disabled="currentComponentIndex >= (steps.length-1)"
                    @click="next"
                >
                    {{ nextStepButtonName }}
                </el-button>

                <el-button
                    v-if="currentComponentIndex == 4"
                    type="primary"
                    @click="onSubmit"
                >
                    提交
                </el-button>
            </div>
        </div>
    </xx-layout>
</template>
<script>
import PageOne from './pageOne';
import PageTwo from './pageTwo';
import PageThree from './pageThree';
import PageFour from './pageFour';
import PageFive from './pageFive';

const compsInfo = {
    pageOne: {
        compId: 'pageOne', label: '第一页', status: 'process', index: 1,
    },
    pageTwo: {
        compId: 'pageTwo', label: '第二页', status: 'process', index: 2,
    },
    pageThree: {
        compId: 'pageThree', label: '第三页', status: 'process', index: 3,
    },
    pageFour: {
        compId: 'pageFour', label: '第四页', status: 'process', index: 4,
    },
    pageFive: {
        compId: 'pageFive', label: '第五页', status: 'process', index: 5,
    },
};

const steps = Object.values(compsInfo).sort((a, b) => a.index - b.index);
export default {
    components: {
        PageOne,
        PageTwo,
        PageThree,
        PageFour,
        PageFive,

    },
    props: {},
    data() {
        return {
            currentComponentIndex: 0,
            entireData: {
                // 第一页数据
                pageOne: {
                    name: '',
                    region: '',
                    delivery: false,
                    type: [],
                    resource: '',
                    desc: '',
                },
                // 第二页数据
                pageTwo: {
                    name: '',
                    region: '',
                    delivery: false,
                    type: [],
                    resource: '',
                    desc: '',
                },
                // 第三页数据
                pageThree: {
                    name: '',
                    region: '',
                    delivery: false,
                    type: [],
                    resource: '',
                    desc: '',
                },
                // 第四页数据
                pageFour: {
                    name: '',
                    region: '',
                    delivery: false,
                    type: [],
                    resource: '',
                    desc: '',
                },
                // 第五页数据
                pageFive: {
                    name: '',
                    region: '',
                    delivery: false,
                    type: [],
                    resource: '',
                    desc: '',
                },
            },
        };
    },
    computed: {
        steps() {
            // 第一页
            if (this.currentComponentIndex === 0) {
                return steps;
            } else {
                // 如果存在内容信息页,则过滤掉steps中内容信息部分
                return steps;
            }
        },
        nextStepButtonName() {
            return '下一步';
        },
        // 下一个组件
        currentComponent() {
            return this.steps[this.currentComponentIndex] &&             
                   this.steps[this.currentComponentIndex].compId;
        },
    },
    methods: {
        // 上一步
        pre() {
            this.currentComponentIndex -= 1;
            this.steps[this.currentComponentIndex].status = 'process';
        },
        // 下一步
        async next() {
            // 第一页
            if (this.currentComponentIndex + 1 === 1) {
                await this.$refs.pageOne.pageOneSubmitForm();
            }
            // 第二页
            if (this.currentComponentIndex + 1 === 2) {
                await this.$refs.pageTwo.pageTwoSubmitForm();
            }
            // 第三页
            if (this.currentComponentIndex + 1 === 3) {
                await this.$refs.pageThree.pageThreeSubmitForm();
            }
            // 第四页
            if (this.currentComponentIndex + 1 === 4) {
                await this.$refs.pageFour.pageFourSubmitForm();
            }
            // 第五页
            if (this.currentComponentIndex + 1 === 5) {
                await this.$refs.pageFive.pageFiveSubmitForm();
            }

            // 下一步 要标记为完成
            this.steps[this.currentComponentIndex].status = 'success';
            this.currentComponentIndex += 1;
        },
        // 暂存  调接口把entireData传给接口即可
        save() {

        },
        // 提交  调接口把entireData传给接口即可
        onSubmit() {

        },
    },
};
</script>
<style lang="scss" scoped>
.footer {
    width: 100%;
    height: 40px;
    line-height: 40px;
    padding: 10px 0;
    background-color: #eee;
    text-align: center;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 2;
    box-sizing: content-box;
}
</style>

第一页的子组件

javascript 复制代码
<template>
    <xx-layout>
        <div
            slot="content"
            class="hierarchy-tag-main"
        >
            <h1>第一页</h1>
            <el-form
                ref="ruleForm"
                :model="ruleForm"
                :rules="rules"
                label-width="100px"
                class="demo-ruleForm"
            >
                <el-form-item
                    label="活动名称"
                    prop="name"
                >
                    <el-input v-model="ruleForm.name" />
                </el-form-item>
                <el-form-item
                    label="活动区域"
                    prop="region"
                >
                    <el-select
                        v-model="ruleForm.region"
                        placeholder="请选择活动区域"
                    >
                        <el-option
                            label="区域一"
                            value="shanghai"
                        />
                        <el-option
                            label="区域二"
                            value="beijing"
                        />
                    </el-select>
                </el-form-item>

                <el-form-item
                    label="即时配送"
                    prop="delivery"
                >
                    <el-switch v-model="ruleForm.delivery" />
                </el-form-item>
                <el-form-item
                    label="活动性质"
                    prop="type"
                >
                    <el-checkbox-group v-model="ruleForm.type">
                        <el-checkbox
                            label="美食/餐厅线上活动"
                            name="type"
                        />
                        <el-checkbox
                            label="地推活动"
                            name="type"
                        />
                        <el-checkbox
                            label="线下主题活动"
                            name="type"
                        />
                        <el-checkbox
                            label="单纯品牌曝光"
                            name="type"
                        />
                    </el-checkbox-group>
                </el-form-item>
                <el-form-item
                    label="特殊资源"
                    prop="resource"
                >
                    <el-radio-group v-model="ruleForm.resource">
                        <el-radio label="线上品牌商赞助" />
                        <el-radio label="线下场地免费" />
                    </el-radio-group>
                </el-form-item>
                <el-form-item
                    label="活动形式"
                    prop="desc"
                >
                    <el-input
                        v-model="ruleForm.desc"
                        type="textarea"
                    />
                </el-form-item>
            </el-form>
        </div>
    </xx-layout>
</template>
<script>
export default {
    props: {
        entireData: {
            type: Object,
            default: () => ({}),
        },
    },
    data() {
        return {
            ruleForm: this.entireData.pageOne,
            rules: {
                name: [
                    { required: true, message: '请输入活动名称', trigger: 'blur' },
                    {
                        min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur',
                    },
                ],
                region: [
                    { required: true, message: '请选择活动区域', trigger: 'change' },
                ],

                type: [
                    {
                        type: 'array', required: true, message: '请至少选择一个活动性质', trigger: 'change',
                    },
                ],
                resource: [
                    { required: true, message: '请选择活动资源', trigger: 'change' },
                ],
                desc: [
                    { required: true, message: '请填写活动形式', trigger: 'blur' },
                ],
            },
        };
    },
    methods: {
        pageOneSubmitForm(formName = 'ruleForm') {
            return new Promise((resolve) => {
                this.$refs[formName].validate((valid) => {
                    if (valid) {
                        resolve(true);
                    } else {
                        return false;
                    }
                });
            });
        },
    },
};
</script>
<style lang="scss" scoped>
.footer {
    width: 100%;
    height: 40px;
    line-height: 40px;
    padding: 10px 0;
    background-color: #eee;
    text-align: center;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 2;
    box-sizing: content-box;
}
</style>

第二页-第五页和第一页结构一样. 只有(数据: ruleForm: this.entireData.pageOne)和(方法pageOneSubmitForm ) 这两个地方不一样, 稍微改一下就行.这里就不贴代码了.

其他的地方可以根据自己的需求改.

相关推荐
也无晴也无风雨1 小时前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang1 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄4 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、4 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
郝晨妤6 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
AvatarGiser6 小时前
《ElementPlus 与 ElementUI 差异集合》Icon 图标 More 差异说明
前端·vue.js·elementui
喝旺仔la6 小时前
vue的样式知识点
前端·javascript·vue.js
别忘了微笑_cuicui6 小时前
elementUI中2个日期组件实现开始时间、结束时间(禁用日期面板、控制开始时间不能超过结束时间的时分秒)实现方案
前端·javascript·elementui