使用递归解决嵌套页面的状态改变

场景

一个注销页,里面有四种状态。

  1. 注销说明页
  2. 输入手机号码和图形验证码
  3. 输入短信验证码
  4. 注销处理中

在每一个状态中,都需要被APP调用window.jumpOther()返回到上一个状态

<template>
    <div v-if="pageStatus.isDelete"></div>
    <div v-if="pageStatus.isInputPhone"></div>
    <div v-if="pageStatus.isInputSms"></div>
    <div v-if="pageStatus.isSuccess"></div>
</template>
<script setup>
const pageStatus = reactive({
	isDelete: true,
	isInputPhone: false,
	isInputSms: false,
	isSuccess: false
})
</script>

 问题

一开始使用一层一层手写的方式去进行window.jumpOther()内容改写,导致代码不符合开闭原则

如果这个单页面有大量的状态需要嵌套,这种方法明显是不可行的的

window.jumpOther = () => {
    updatePageStatus(pageStatus, 'isInputPhone')
    window.jumpOther = () => {
        updatePageStatus(pageStatus, 'isDelete')
        window.jumpOther = () => {
            goSetting()
        }
    }
}

思路和解决

由于是嵌套,很容易想到递归的思想,利用递归去拼接我们需要的嵌套window.jumpOther()

可以先给出一个状态数组,里面存放了每个状态的名称和对应的jumpOther()方法

const pages = [
    {
        pageName: 'isDelete',
        jumpOther: () => {
            console.log(1)
        },
    },
    {
        pageName: 'isInputPhone',
        jumpOther: () => {
            updatePageStatus(pageStatus, 'isDelete')
            console.log(2)
        },
    },
    {
        pageName: 'isInputSms',
        jumpOther: () => {
            updatePageStatus(pageStatus, 'isInputPhone')
            console.log(3)
        },
    },
    {
        pageName: 'isSuccess',
        jumpOther: () => {
            updatePageStatus(pageStatus, 'isInputSms')
            console.log(4)
        },
    },
]
  • 首先我的想法是找到当前状态的位置,然后从当前位置做递减,将所有前列jumpOther进行嵌套。但是这样并不好实现,从而改为从头开始,向上嵌套。
  • 然后通过记录当前的window.jumpOther()作为上一次的jumpOther,作为参数传给下一次调用,这样下一次调用将参数(上一次的jumpOther)拼接到自身下
  • 传入一个idx作为标识符用来与当前状态的位置作比较,同时作为跳出递归的条件
const updatePageStatus = (statusList, updatedPage) => {
    Object.keys(statusList).forEach(s => {
        statusList[s] = false
    })
    statusList[updatedPage] = true
}
const handleSetJumpOther = (lastJump, pageRange, idx) => {
    if (pageRange === 0) {
        window.jumpOther = pages[idx].jumpOther
        return
    }
    if (idx === pageRange) return
    window.jumpOther = () => {
        pages[idx].jumpOther()
        window.jumpOther = lastJump
    }
    idx += 1
    handleSetJumpOther(window.jumpOther, pageRange, idx)
}
handleSetJumpOther(pages[0].jumpOther, pageRange, 0)

存在问题

  1.  第一个参数意义为上一次的jumpOther,第一次调用的时候应该传一个空值。但是实际上需要传第一个状态的jumpOther

完整代码

const pageStatus = {
    isDelete: false,
    isInputPhone: false,
    isInputSms: false,
    isSuccess: true,
}

const pages = [
    {
        pageName: 'isDelete',
        jumpOther: () => {
            console.log(1)
        },
    },
    {
        pageName: 'isInputPhone',
        jumpOther: () => {
            updatePageStatus(pageStatus, 'isDelete')
            console.log(2)
        },
    },
    {
        pageName: 'isInputSms',
        jumpOther: () => {
            updatePageStatus(pageStatus, 'isInputPhone')
            console.log(3)
        },
    },
    {
        pageName: 'isSuccess',
        jumpOther: () => {
            updatePageStatus(pageStatus, 'isInputSms')
            console.log(4)
        },
    },
]

const findCurrentPageRange = () => {
    const currentPage = Object.keys(pageStatus).find(p => {
        return pageStatus[p] === true
    })
    return pages.findIndex(p => {
        return p.pageName === currentPage
    })
}

const updatePageStatus = (statusList, updatedPage) => {
    Object.keys(statusList).forEach(s => {
        statusList[s] = false
    })
    statusList[updatedPage] = true
}

const handleSetJumpOther = (lastJump, pageRange, idx) => {
    if (pageRange === 0) {
        window.jumpOther = pages[idx].jumpOther
        return
    }
    if (idx === pageRange) return
    window.jumpOther = () => {
        pages[idx].jumpOther()
        window.jumpOther = lastJump
    }
    idx += 1
    handleSetJumpOther(window.jumpOther, pageRange, idx)
}

handleSetJumpOther(pages[0].jumpOther, findCurrentPageRange(), 0)

 

posted on 2024-01-23 17:55  Karle  阅读(1)  评论(0编辑  收藏  举报