知识点补充一:PropType
vue3为结合 ts
,props设置自定类型
import { defineComponent, PropType } from "vue";
props: {formItem: {type: Array as PropType < IFormItemType[] > ,default:() &#61; >[]}
}
知识点补充二&#xff1a;require.context方法
webpack的函数&#xff1a;根据传入的参数&#xff0c;获取对应文件的相对路径&#xff0c;返回值调用.keys()
方法和得到路径的数组。
权限管理&#xff1a;根据传递对来的路径&#xff0c;去匹配对应的route&#xff0c;设置动态路由
import type { RouteRecordRaw } from "vue-router";
export default function (useMenus: any[]): RouteRecordRaw[] {const routes: RouteRecordRaw[] &#61; [];const allRoutes: RouteRecordRaw[] &#61; [];const routeFiles &#61; require.context("&#64;/router/main", true, /\.ts$/);routeFiles.keys().forEach((filePath) &#61;> {const routeModule &#61; require("&#64;/router/main" &#43; filePath.split(".")[1]);allRoutes.push(routeModule.default);});console.log(useMenus);function findRouteFun(useMenus: any[]) {for (const menu of useMenus) {if (menu.type &#61;&#61;&#61; 1) {findRouteFun(menu.children);} else if (menu.type &#61;&#61;&#61; 2) {const route &#61; allRoutes.find((item) &#61;> item.path &#61;&#61;&#61; menu.url);if (route) {routes.push(route);}}}}findRouteFun(useMenus);console.log(routes);return routes;
}
组件二次封装
传入对应的配置信息可马上获取一个新的组件
index.ts
总出口文件
import MsiForm from "./src/MsiForm.vue";export * from "./types";
export default MsiForm;
types.ts
文件
type InputType &#61; "input" | "select" | "password" | "datapicker";export interface IFormItemType {type: InputType;label: string;rules?: any[];placeholder?: string;options?: any[];otherOptions?: any;
}interface colLayoutType {xs?: number;sm?: number;md?: number;lg?: number;xl?: number;
}
export interface IForm {formItem: IFormItemType[];labelWidth?: string;itemStyle?: any;colLayout?: colLayoutType;
}
MsiForm.vue
组件
<template><div class&#61;"msi-form"><el-form :label-width&#61;"labelWidth"><el-row><template v-for&#61;"item in formItem" :key&#61;"item.label"><el-col :&#61;"colLayout"><el-form-item :label&#61;"item.label" :style&#61;"itemStyle"><template v-if&#61;"item.type &#61;&#61;&#61; &#39;input&#39;"><el-input:placeholder&#61;"item.placeholder"v-bind&#61;"item.otherOptions"/></template><template v-else-if&#61;"item.type &#61;&#61;&#61; &#39;password&#39;"><el-inputshow-password:placeholder&#61;"item.placeholder"v-bind&#61;"item.otherOptions"/></template><template v-else-if&#61;"item.type &#61;&#61;&#61; &#39;select&#39;"><el-selectv-bind&#61;"item.otherOptions":placeholder&#61;"item.placeholder ? item.placeholder : &#39;请选择..&#39;"><el-optionv-for&#61;"option in item.options":key&#61;"option.value":value&#61;"option.value">{{ option.title }}</el-option></el-select></template><template v-else-if&#61;"item.type &#61;&#61;&#61; &#39;datapicker&#39;"><el-date-picker v-bind&#61;"item.otherOptions"/></template></el-form-item></el-col></template></el-row></el-form></div>
</template><script lang&#61;"ts">
import { defineComponent, PropType } from "vue";
import type { IFormItemType } from "../types";export default defineComponent({name: "index",props: {formItem: {type: Array as PropType<IFormItemType[]>,default: () &#61;> []},labelWidth: {type: String,default: "80px"},itemStyle: {type: Object,default: () &#61;> ({ padding: "10px 20px" })},colLayout: {type: Object,default: () &#61;> ({xs: 24,sm: 24,md: 12,lg: 8,xl: 6})}},setup() {return {};}
});
</script><style lang&#61;"less" scoped>
.msi-form {padding-top: 20px;width: 100%;background-color: #fff;border-radius: 10px;
}
</style>