通过状态思维应对多变页面
刀刀
4/7/2025
0 字
0 分钟
状态思维
有的时候会碰到页面会基于各种因素,来产生很多变化的情况,与其一个个做判断,不妨把页面归纳为几种状态,把多个因素统一归为几种状态。然后用数据定义好每种状态下的展示。这样就只用关心修改状态,定义不同状态下的数据就好。
案例分析
下面有一个页面,根据不同的状态,展示不同的内容:
用户一进入页面,此时没有
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
判断修改当前最新的页面状态。