切换状态是一个比较常见的操作,通常会这么进行切换:
常规操作
let state: boolean = true
function toggle(): boolean { this.state = !this.state return this.state }
|
更通用一点的写法会进行一个封装:
class Switch { private state:boolean
constructor(initState: boolean) { this.state = initState }
getState(): boolean { return this.state }
toggle(): boolean { this.state = !this.state return this.getState() } }
|
更改状态的表示方法
如果是文字状态切换呢?可能会这么写:
const switcher = new Switch(false)
let currentState = switcher.getState() currentState ? 'on' : 'off'
|
或许你会想到可以更改 Switch 的定义:
class Switch { private state: boolean private trueState: string private falseState: string
constructor(initState: boolean, trueState: string, falseState: string) { this.state = initState this.trueState = trueState this.falseState = falseState }
toggle(): boolean { this.state = !this.state return this.getState() }
getState(): boolean { return this.state } }
|
切换多个状态
在有些场合,会有有多个状态进行切换,比如十字路口的灯有红黄绿三种状态切换,这个时候应该想到可以使用数组。
这里直接一步到位,使用泛型,支持任意的状态类型切换:
class Switch<T> { private index: number private state: T[] constructor(initState: T, state: T[]) { this.state = state this.index = state.indexOf(initState) } getState(): T { return this.state[this.index] } toggle(): T { this.index = (this.index + 1) % this.state.length return this.getState() } }
const switcher = new Switch('红', ['红', '黄', '绿']) console.log(switcher.toggle()) console.log(switcher.toggle()) console.log(switcher.toggle())
|
使用泛型,当然也支持函数,比如根据不同的状态执行不同的操作:
const redFn = () => console.log('红灯,禁止通行') const yellowFn = () => console.log('黄灯,谨慎通行') const greenFn = () => console.log('绿灯,畅通无阻') const roadSwitcher = new Switch(redFn, [redFn, yellowFn, greenFn]) roadSwitcher.getState()() roadSwitcher.toggle()() roadSwitcher.toggle()() roadSwitcher.toggle()()
|
高阶函数
除了使用类,使用高阶函数也是可以做到的:
function switchFn<T>(initState: T, state: T[]) { let index: number = state.indexOf(initState) return function() { index = (index + 1) % state.length return state[index] } }
const switcher = switchFn('红', ['红', '黄', '绿']) console.log(switcher()) console.log(switcher()) console.log(switcher()) console.log(switcher())
const redFn = () => console.log('红灯,禁止通行') const yellowFn = () => console.log('黄灯,谨慎通行') const greenFn = () => console.log('绿灯,畅通无阻') const roadSwitcher = switchFn(redFn, [redFn, yellowFn, greenFn]) roadSwitcher()() roadSwitcher()() roadSwitcher()() roadSwitcher()()
|
生成器 Generator
遍历多个状态时,也可以使用 Generator
function *loop<T>(initIndex: number, list: T[]){ let currentIndex: number = initIndex
while(true){ currentIndex = (currentIndex + 1) % list.length yield list[currentIndex] } }
function switchFn<T>(initState: T, state: T[]) { const list = loop(state.indexOf(initState), state) return function() { return list.next().value as T } }
|
自定义 hook
const useSwitch = <T extends unknown >(initialValue: T, stateList: T[]): [T, () => void] => { const switcher = switchFn(initialValue, stateList); const [state, setState] = useState<T>(switcher(false));
return [state, () => { setState(switcher(true)); }]; }
|