一. 研究 vant useToggle 源码,发现只支持布尔值,源码如下:
import { ref } from 'vue';
export function useToggle(defaultValue = false) {
const state = ref(defaultValue);
const toggle = (value = !state.value) => {
state.value = value;
};
return [state, toggle] as const;
}
二. 又研究了a-hook useToggle 源码,发现洋洋洒洒70行(太繁琐了),源码如下:
import { ref, Ref } from 'vue-demi';
type IState = string | number | boolean | undefined;
export function useToggle<T = boolean | undefined>(): {
state: Ref<boolean>;
toggle: (value?: T) => void;
setLeft: () => void;
setRight: () => void;
};
export function useToggle<T = IState>(
defaultValue: T,
): {
state: Ref<T>;
toggle: (value?: T) => void;
setLeft: () => void;
setRight: () => void;
};
export function useToggle<T = IState, U = IState>(
defaultValue: T,
reverseValue: U,
): {
state: Ref<T | U>;
toggle: (value?: T | U) => void;
setLeft: () => void;
setRight: () => void;
};
export function useToggle<D extends IState = IState, R extends IState = IState>(
defaultValue: D = false as D,
reverseValue?: R,
) {
const state = ref<D | R>(defaultValue);
const setState = (value: D | R) => {
// TODO
state.value = value as any;
};
const reverseValueOrigin = (reverseValue === undefined
? !defaultValue
: reverseValue) as D | R;
// 切换返回值
const toggle = (value: D | R) => {
if (value === undefined) {
value = state.value === defaultValue ? reverseValueOrigin : defaultValue;
}
setState(value);
};
// 设置默认值
const setLeft = () => {
setState(defaultValue);
};
// 设置取反值
const setRight = () => {
setState(reverseValueOrigin);
};
return {
state,
toggle,
setLeft,
setRight,
};
}
三. 就想要一种优雅、强大、极简的实现方式,最终实现如下:
- 默认是布尔值翻转;
- 支持任意翻转值对(数组支持的所有混合类型都支持);
import { ref } from 'vue';
const useToggle = (value = false, toggleValue = true) => {
const state = ref(value);
const toggle = (newValue) => {
if ([value, toggleValue].includes(newValue)) {
state.value = newValue;
return;
}
state.value = (state.value === value ? toggleValue : value);
}
return {
state,
toggle
}
}
export{
useToggle,
}
🌰🌰:
// example:
// const { state, toggle } = useToggle();
// const { state: state1, toggle: toggle1} = useToggle("a", "b");
// const { state: state2, toggle: toggle2} = useToggle(1, null);