可扩展为其他弹窗组件
import { render, createVNode, ref, nextTick } from "vue";
import PopupPicker from "@/components/popup-picker.vue";
import { CustomToast } from "@/utils";
interface ICustom {
text: string;
value: string;
children?: string;
}
interface IPicker {
dictKey?: string;
columns?: Array<any>;
confirm: (e: any) => void;
title?: string;
show?: boolean;
maskClick?: boolean;
value?: Array<any>;
confirmText?: string;
hasAll?: boolean;
dictApi?: boolean;
customFieldName?: ICustom;
optionNum?: number;
change?: (e: any) => void;
cancel?: () => void;
}
/**
* showPicker 函数式调用picker弹窗
* @param { string } dictKey 字典key 与columns 二者取其一
* @param { Array<any> } columns 数据列表, 与dictKey 二者取其一
* @param { Function } confirm 确定回调,必传
* @param { string } title picker标题
* @param { Array<string> } value 回显value值
* @param { string } confirmText 确认按钮文字
* @param { boolean } maskClick 点击遮罩关闭
* @param { boolean } hasAll 数据列表内是否增加全部,也可自己在数据列表内增加,仅支持单列
* @param { boolean } dictApi 是否获取接口字典的数据,需要传dictKey
* @param { Object } customFieldName 自定义 columns 结构中的字段
* @param { Object } optionNum 可见的选项个数,默认5
* @param { Function } change 选中的选项改变时触发回调
* @param { Function } cancel 点击取消时触发回调
* @returns
showPicker({
title: "picker组件",
value: ['0'],
columns: [{text:'选项1', value:'0'}],
confirm: (e: any) => {},
});
*/
const showPicker = (props: IPicker) => {
const {
value,
dictKey,
columns,
title,
confirmText,
maskClick,
hasAll,
customFieldName,
optionNum,
dictApi,
confirm,
change,
cancel,
} = props;
if (value && !Array.isArray(value)) return CustomToast("value值必须为数组");
if (!columns && !dictKey) return CustomToast("未获取到数据");
if (
customFieldName &&
(!("text" in customFieldName) || !("value" in customFieldName))
)
return CustomToast("customFieldName传入类型错误");
// 数据增加全部
let processedColumns = [] as Array<any>;
if (columns) {
processedColumns = [...columns];
if (hasAll && !processedColumns.some((item) => "children" in item)) {
processedColumns.unshift({
[customFieldName?.text ?? "text"]: "全部",
[customFieldName?.value ?? "value"]: "",
});
}
}
const container = document.createElement("div");
document.body.appendChild(container);
// 增加popup动画
const show = ref(false);
const onConfirm = (e: any) => {
confirm && confirm(e);
show.value = false;
cleanup();
};
const onChange = (e: any) => {
change && change(e);
};
const onCancel = () => {
cancel && cancel();
show.value = false;
cleanup();
};
const vNode = createVNode(PopupPicker, {
show: show.value,
maskClick: maskClick ?? false,
columns: processedColumns,
dictKey: dictKey,
title,
value: value ?? [],
confirmText: confirmText ?? "确认",
customFieldName: customFieldName ?? {
text: "text",
value: "value",
children: "children",
},
optionNum: optionNum ?? 5,
dictApi: dictApi ?? false,
hasAll:
(hasAll && !processedColumns.some((item) => "children" in item)) ?? false,
onConfirm,
onChange: onChange,
onCancel: onCancel,
"onUpdate:show": (val: boolean) => {
show.value = val;
},
});
render(vNode, container);
nextTick(() => {
show.value = true;
if (vNode.component) {
vNode.component.props.show = true;
vNode.component.proxy?.$forceUpdate();
}
});
const cleanup = () => {
setTimeout(() => {
render(null, container);
document.body.removeChild(container);
}, 300); // 这里增加延迟,是为了popup关闭动画展示
};
};
export default showPicker;