知识点补充一:PropType
vue3为结合
ts
,props设置自定类型
import { defineComponent, PropType } from "vue";
// ....代码省略
props: {
formItem: {
type: Array as PropType < IFormItemType[] > ,
default:() = >[]
}
}
知识点补充二:require.context方法
webpack的函数:根据传入的参数,获取对应文件的相对路径,返回值调用
.keys()
方法和得到路径的数组。
权限管理:根据传递对来的路径,去匹配对应的route,设置动态路由
import type { RouteRecordRaw } from "vue-router";
export default function (useMenus: any[]): RouteRecordRaw[] {
const routes: RouteRecordRaw[] = [];
// 加入全部路由
const allRoutes: RouteRecordRaw[] = [];
const routeFiles = require.context("@/router/main", true, /\.ts$/);
routeFiles.keys().forEach((filePath) => {
const routeModule = require("@/router/main" + filePath.split(".")[1]);
allRoutes.push(routeModule.default);
});
console.log(useMenus);
// 递归函数 获取可点击部分的url,并进行筛选
function findRouteFun(useMenus: any[]) {
for (const menu of useMenus) {
if (menu.type === 1) {
findRouteFun(menu.children);
} else if (menu.type === 2) {
const route = allRoutes.find((item) => item.path === 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 = "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="msi-form">
<el-form :label-width="labelWidth">
<el-row>
<template v-for="item in formItem" :key="item.label">
<el-col :="colLayout">
<el-form-item :label="item.label" :style="itemStyle">
<template v-if="item.type === 'input'">
<el-input
:placeholder="item.placeholder"
v-bind="item.otherOptions"
/></template>
<template v-else-if="item.type === 'password'">
<el-input
show-password
:placeholder="item.placeholder"
v-bind="item.otherOptions"
/></template>
<template v-else-if="item.type === 'select'">
<el-select
v-bind="item.otherOptions"
:placeholder="
item.placeholder ? item.placeholder : '请选择..'
"
>
<el-option
v-for="option in item.options"
:key="option.value"
:value="option.value"
>{{ option.title }}</el-option
>
</el-select>
</template>
<template v-else-if="item.type === 'datapicker'">
<el-date-picker v-bind="item.otherOptions"
/></template>
</el-form-item>
</el-col>
</template>
</el-row>
</el-form>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from "vue";
import type { IFormItemType } from "../types";
export default defineComponent({
name: "index",
props: {
formItem: {
type: Array as PropType<IFormItemType[]>,
default: () => []
},
labelWidth: {
type: String,
default: "80px"
},
itemStyle: {
type: Object,
default: () => ({ padding: "10px 20px" })
},
colLayout: {
type: Object,
default: () => ({
xs: 24,
sm: 24,
md: 12,
lg: 8,
xl: 6
})
}
},
setup() {
return {};
}
});
</script>
<style lang="less" scoped>
.msi-form {
padding-top: 20px;
width: 100%;
background-color: #fff;
border-radius: 10px;
}
</style>