通过状态思维应对多变页面
状态思维
有的时候会碰到页面会基于各种因素,来产生很多变化的情况,与其一个个做判断,不妨把页面归纳为几种状态,把多个因素统一归为几种状态。然后用数据定义好每种状态下的展示。这样就只用关心修改状态,定义不同状态下的数据就好。
案例分析
下面有一个页面,根据不同的状态,展示不同的内容:
用户一进入页面,此时没有
key值,要有一个输入框和确认按钮,让用户输入key值。
用户输入
key值后,还未确认,输入框隐藏,有一个文本显示当前的key值,按钮内容变为 “我已确认无误,使用 key”。
点击确认无误按钮后页面存在
key值了,页面由显示key值的文本和按钮组成,按钮内容变为 “修改”。
点击修改按钮后进入修改状态,页面多出一个输入框,按钮内容变为 “确认修改”。

最后点击确认修改的按钮后,询问用户是否要使用新
key值。
思考实现
现在来想想要如何实现这个需求案例,根据上面的分析,可以把页面分为 5 种状态,每种状态用一个英文单词来表示,如:第一个无 key 无确认,可以定义为 unbind ;第二个是无 key 待确认,可以定义为 awaitBind ;第三个是有 key 待修改,可以定义为 binded ;第四个是有 key 正在修改,可以定义为 changing ;第五个是有 key 待确认,可以定义为 awaitChang 。
然后定义一个变量,把上方的 5 种状态都作为该对象的键名。键值为一个对象,对象里定义该状态下需要展示什么内容,如【是输入框,是按钮,还是文本内容等】;以及文本内容,如【按钮的文本内容和输入框前面的文本内容】。
定义好了变量后,通过Vue的计算属性 computed 提取对应状态对象,通过该对象来动态渲染DOM元素即可。页面DOM元素根据上方五个示例图,可以划分为上中下三块。上方可能是文本,可能是输入框;中间是输入框或文本或空;下方是按钮,只不过内容不一样。
const pageState = ref('unbind') // 当前页面的状态
const now = ref('') // 第一区域的输入框或文本要显示的内容
const pre = ref('') // 第二区域的输入框或文本要显示的内容
const stateObj = {
unbind: {
nowLabel: '请输入key值',
nowType: 'input',
buttonText: '确认',
buttonClick: () => {}
},
awaitBind: {
nowLabel: '待确认key值',
nowType: 'span',
buttonText: '我已确认无误,使用key',
buttonClick: () => {}
},
binded: {
nowLabel: '你的key值',
nowType: 'span',
buttonText: '修改',
buttonClick: () => {}
},
changing:: {
nowLabel: '当前key值',
nowType: 'span',
preLabel: '要修改为',
preType: 'input',
buttonText: '确认修改',
buttonClick: () => {}
},
awaitChang:: {
nowLabel: '当前key值',
nowType: 'span',
preLabel: '要修改为',
preType: 'span',
buttonText: '确认使用新key',
buttonClick: () => {}
},
}
const state = computed(() => {
return stateObj[pageState.value]
})<template>
<div v-if="state.nowLabel && state.nowType">
<span>{{ state.nowLabel }}</span>
<input v-if="state.nowType === 'input'" v-model="now" />
<span v-if="state.nowType === 'span'">{{ now }}</span>
</div>
<div v-if="state.preLabel && state.preType">
<span>{{ state.preLabel }}</span>
<input v-if="state.preType === 'input'" v-model="pre" />
<span v-if="state.preType === 'span'">{{ pre }}</span>
</div>
<div>
<button @click="state.buttonClick">{{ state.buttonText }}</button>
</div>
</template>进入页面的时候需要先判断用户上一次执行到哪一个状态步骤了,方便用户接下去。因此需要先调用接口获取 now 和 pre 的值,分为以下几种状态:
- 有
now值有pre值,说明执行到awaitChang状态 - 有
now值无pre值,说明执行到binded状态 - 无
now值有pre值,说明执行到awaitBind状态 - 无
now值无pre值,说明执行到unbind状态
function getNowKeyState() {
axios.get('/xxx').then((res) => {
const data = res.data.data
now.value = data.now
pre.value = data.pre
if (data.now) {
if (data.pre) pageState.value = 'awaitChang'
else pageState.value = 'binded'
} else {
if (data.pre) pageState.value = 'awaitBind'
else pageState.value = 'unbind'
}
})
}
getNowKeyState()现在页面状态结构已经实现了,接下来就是实现每个状态下的按钮点击事件了。每一个点击事件都调用各自的接口,成功后调用上方的方法 getNowKeyState 判断修改当前最新的页面状态。