UNPKG

@fesjs/fes-design

Version:
102 lines (94 loc) 4.07 kB
import _defineProperty from '@babel/runtime/helpers/esm/defineProperty'; import { ref, watch, computed } from 'vue'; import { isUndefined, isArray, isEqual } from 'lodash-es'; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } const useNormalModel = function (props, emit) { let config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; const { prop = 'modelValue', deep = false, isEqual: isEqual$1 = false, defaultValue } = config; const usingProp = prop; // 实际使用中 'modelValue' 本就应该在 Key 中 // NOTE: 不可以使用 ref<Type> 的写法,currentValue 会被直接推导成 Props[Key] const currentValue = ref(!isUndefined(props[usingProp]) ? props[usingProp] : defaultValue); const pureUpdateCurrentValue = value => { if (value === currentValue.value || isEqual$1 && isEqual(value, currentValue.value)) { return; } currentValue.value = value; }; const updateCurrentValue = value => { pureUpdateCurrentValue(value); // TODO: need a more proper way instead of `as` emit(`update:${usingProp}`, currentValue.value); }; watch(() => props[usingProp], val => { if (val === currentValue.value) { return; } currentValue.value = val; }, { deep }); return [computed({ get() { return currentValue.value; }, set(value) { updateCurrentValue(value); } }), updateCurrentValue]; }; // type IncludeArray<U> = U extends unknown[] ? U : never; // type ExtractArray<U> = U extends unknown[] ? U : never; /** * TODO: 后续优化 * 使得 useArrayModel 在不传 config 使用 modelValue,且 modelValue 的类型不为数组的情况下,有更友好的类型报错提示 * 目前在上述情况下,modelValue 的类型被推导为 never,保证了部分场景。 */ /* type UseArrayModelReturn< Props extends Record<string, any>, Key extends keyof Props, > = Props[Key] extends never ? never : [WritableComputedRef<Props[Key]>, (val: ArrayOrItem<Props[Key]>) => void]; */ const useArrayModel = function (props, emit) { let config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; const [computedValue, updateCurrentValue] = useNormalModel(props, emit, _objectSpread(_objectSpread({}, config), {}, { defaultValue: [] })); if (!isArray(computedValue.value)) { console.warn('[useArrayModel] 绑定值类型不匹配, 仅支持数组类型, value:', props[(config === null || config === void 0 ? void 0 : config.prop) || 'modelValue']); updateCurrentValue([]); } const updateItem = value => { if (isArray(value)) { updateCurrentValue(value); return; } // 兼容重复赋值为不符合预期数据类型的场景 let val = []; if (!isArray(computedValue.value)) { console.warn('[useArrayModel] 绑定值类型不匹配, 仅支持数组类型, value:', computedValue.value); val = []; } else { val = [...computedValue.value]; } const index = val.indexOf(value); if (index !== -1) { val.splice(index, 1); } else { val.push(value); } updateCurrentValue(val); }; return [computedValue, updateItem]; }; /** * useArrayModel 的返回值 * 用于 modelValue 混杂了 useNormalModel 类型的情况,用于手动指明 useArrayModel 需要的 modelValue 类型 */ export { useArrayModel, useNormalModel };