前言
希望能够把一些有很多复杂状态的页面分离清楚,方便后续针对不同的情况加功能。
使用前
computed: {
// 状态名称
statusText () {
switch (this.status) {
case 1:
return '未处理'
case 2:
return '处理中'
case 3:
return '已发布'
case 4:
return '已下架'
case 5:
return '无效批'
}
return ''
},
// 状态tag的颜色
statusColor () {
switch (this.status) {
case 1:
return 'blue'
case 2:
return 'green'
case 3:
return 'orange'
case 4:
case 5:
return 'default'
}
return ''
},
// 展示“设置为无效”按钮
showInvalidBtn () {
const _no_attach = this.statusText === '处理中' && !this.hasAttachment
const _has_attach = this.hasAttachment && ['处理中', '已下架'].includes(this.statusText)
return _no_attach || _has_attach
},
}
问题所在
不容易看懂这个业务状态的走向,不方便后面加功能,容易混淆加犯错。\
使用状态机(vue2)
- State (状态)。一个状态机至少要包含两个状态。例如上面任务状态,有 未处理 和 处理中 等等状态。
- Event (事件)。事件就是执行某个操作的触发条件或者口令。
- Action (动作)。事件发生以后要执行动作。对于上面的statusText,statusColor,就是一个动作。
- Transition (变换)。也就是从一个状态变化为另一个状态。
代码层面
创建状态机
class StatusMaker {
constructor (detail) {
if (!detail) return
this.state = this.setState(detail.status)
this.detail = detail
}
}
传入任务的详情数据
增加状态(state)
class StatusMaker {
constructor (detail) {
if (!detail) return
this.state = this.setState(detail.status)
this.detail = detail
}
setState (status) {
if (status === 1) {
return 'type1' // '未处理'
} else if (status === 2) {
return 'type2' // '处理中'
} else if (status === 3) {
return 'type3' // '已发布'
} else if (status === 4) {
return 'type4' // '已下架'
} else if (status === 5) {
return 'type5' // '无效批'
}
}
}
状态是控制状态机运行的关键属性,所以首先得控制传入的任务类型
增加动作(action)
根据当前类型执行需要的不同的方法。
class StatusMaker {
constructor (detail) {
if (!detail) return
this.state = this.setState(detail.status)
this.detail = detail
}
setState (status) {
if (status === 1) {
return 'type1' // '未处理'
} else if (status === 2) {
return 'type2' // '处理中'
} else if (status === 3) {
return 'type3' // '已发布'
} else if (status === 4) {
return 'type4' // '已下架'
} else if (status === 5) {
return 'type5' // '无效批'
}
}
type1 = {
statusText() {
return '未处理'
},
statusColor () {
return 'blue'
}
}
type2 = {
statusText() {
return '处理中'
},
statusColor () {
return 'green'
},
showInvalidBtn () {
return true
},
showReasonModal () {
return this.detail.hasAttachment // 含附件
}
}
type3 = {
statusText() {
return '已发布'
},
statusColor () {
return 'orange'
}
}
type4 = {
statusText() {
return '已下架'
},
statusColor () {
return 'default'
},
showInvalidBtn () {
return this.detail.hasAttachment // 含附件
},
showReasonModal () {
return this.detail.hasAttachment // 含附件
}
}
type5 = {
statusText() {
return '无效批'
},
statusColor () {
return 'default'
}
}
}
增加执行事件event
class StatusMaker {
constructor (detail) {
if (!detail) return
this.state = this.setState(detail.status)
this.detail = detail
}
setState (status) {
if (status === 1) {
return 'type1' // '未处理'
} else if (status === 2) {
return 'type2' // '处理中'
} else if (status === 3) {
return 'type3' // '已发布'
} else if (status === 4) {
return 'type4' // '已下架'
} else if (status === 5) {
return 'type5' // '无效批'
}
}
type1 = {
...
}
...
// ++ start
getEvent (method, ...args) {
const state = this.state
if (!this[state] || !this[state][method]) {
return false
}
// 通过call让action内部能够获取当前实例this,并且将参数args传入
return this[state][method].call(this, ...args)
}
// ++ end
}
vue2使用
import StatusMaker from '@/libs/statusMaker/powerBox.js'
export default {
data() {
return {
statusMaker: null
}
},
created () {
this.init_status()
},
methods: {
init_status () {
this.statusMaker = new StatusMaker(this.detail)
this.statusText = this.statusMaker.getEvent('statusText')
this.statusColor = this.statusMaker.getEvent('statusColor')
this.showInvalidBtn = this.statusMaker.getEvent('showInvalidBtn')
}
}
}
状态机代码
class StatusMaker {
constructor (detail) {
if (!detail) return
this.state = this.setState(detail.status)
this.detail = detail
}
setState (status) {
if (status === 1) {
return 'type1' // '未处理'
} else if (status === 2) {
return 'type2' // '处理中'
} else if (status === 3) {
return 'type3' // '已发布'
} else if (status === 4) {
return 'type4' // '已下架'
} else if (status === 5) {
return 'type5' // '无效批'
}
}
type1 = {
statusText() {
return '未处理'
},
statusColor () {
return 'blue'
}
}
type2 = {
statusText() {
return '处理中'
},
statusColor () {
return 'green'
},
showInvalidBtn () {
return true
},
showReasonModal () {
return this.detail.hasAttachment // 含附件
}
}
type3 = {
statusText() {
return '已发布'
},
statusColor () {
return 'orange'
}
}
type4 = {
statusText() {
return '已下架'
},
statusColor () {
return 'default'
},
showInvalidBtn () {
return this.detail.hasAttachment // 含附件
},
showReasonModal () {
return this.detail.hasAttachment // 含附件
}
}
type5 = {
statusText() {
return '无效批'
},
statusColor () {
return 'default'
}
}
// ++ start
getEvent (method, ...args) {
const state = this.state
if (!this[state] || !this[state][method]) {
return false
}
return this[state][method].call(this, ...args) // 通过call让action内部能够获取当前实例this,并且将参数args传入
}
// ++ end
}
export default StatusMaker