Bootstrap

项目业务<权限管理 + 组件二次封装>

知识点补充一: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>

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;