Geeker Admin框架使用初体验--菜单模块编码

前言

事先说明我只是个正常的前端开发者,没有使用过太多的后台框架, 最近公司要开发一个后台,让前端自己主选后台模板,查看了两时半之后,我选择了这一款Geeker-Admin | 一款简单易用的中后台模版 (spicyboy.cn)

选择它的原因主要是以下几点:

技术栈

技术栈符合我的技术范围,使用的也是比较流行的技术,vite+vue3+ts那一套

功能完整

前端需要的功能大多都完善了,作者大大封装了element的表格系统,代码初看了一遍还是非常方便的,它将搜索栏和操作栏,数据栏都转换为了配置项。

其次我非常喜欢的样式皮肤设置,在这里可以选择各种界面样式,当然暗黑模式也是在这里设置,适应各种管理者的操作习惯。

文档详细

还有一个比较重要的一点是文档详细,作者大大将他的组件都写了详细的文档,清晰易懂,还有各种小细节就不一一介绍了。

使用开发

拉取代码后观看一圈后,我开始尝试着编码菜单模块。

编码前,作者源代码是这样的

没有写弹框以及添加子菜单的操作,然后我就编码了这一个功能。

作为一个大三半年的新手程序员,看完代码之后还是学习到一些写法。

在index.vue同级下创建components/MenuDialog.vue,使用defineExpose将方法暴露给父组件,接收父组件操作名称,字段数据(编辑内容初始化),点击确认调用的api,以及更新表格数据。

html 复制代码
<template>
  <div>
    <el-dialog v-model="dialogShow" :title="FData?.title + '菜单'" width="500">
      <el-form ref="ruleFormRef" label-width="100px" label-suffix=" :" :rules="rules" :model="FData?.row">
        <el-form-item label="路由地址" prop="path">
          <el-input v-model="FData.row!.path" placeholder="请填写路由地址" clearable></el-input>
        </el-form-item>
        <el-form-item label="路由名称" prop="name">
          <el-input v-model="FData.row!.name" placeholder="请填写路由名称" clearable></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="dialogShow = false">取消</el-button>
          <el-button type="primary" @click="handleSubmit()"> 确定 </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts" name="MenuDialog">
import { reactive, ref } from "vue";
import { ElDialog, ElMessage, FormInstance } from "element-plus";
const dialogShow = ref(false);
const FData = ref<FProps>({
  title: "",
  row: {}
});
const rules = reactive({
  path: [{ required: true, message: "请填写路由地址" }],
  name: [{ required: true, message: "请填写路由名称" }]
});

// 提交数据(新增/编辑)
const ruleFormRef = ref<FormInstance>();
const handleSubmit = () => {
  ruleFormRef.value!.validate(async valid => {
    if (!valid) return;
    try {
      await FData.value?.api!(FData.value?.row);
      ElMessage.success({ message: `${FData.value?.title}菜单成功!` });
      FData.value?.getTableList!();
      dialogShow.value = false;
    } catch (error) {
      console.log(error);
    }
  });
};
interface FProps {
  title: string;
  row: Partial<Menu.MenuOptions>;
  api?: (params: any) => Promise<any>;
  getTableList?: () => void;
}
// 接收父组件传过来的参数
const acceptParams = (params: FProps) => {
  FData.value = params;
  dialogShow.value = true;
};

defineExpose({
  acceptParams
});
</script>

<style lang="scss" scoped></style>

由于是假数据,编辑器会报错,换成Promise请求就不会了,代码如下,使用ProTable组件,配置请求api,columns如果api的返回不符合处理规范,使用data-callback可以进行处理。

最后我有样学样的把操作都写在一个方法内,将数据处理后调用子组件方法,值得注意的是我尝试编码是没有写处理api的,把传给子组件的api改成调用的就行。

html 复制代码
<template>
  <div class="table-box">
    <ProTable
      ref="proTable"
      title="菜单列表"
      row-key="path"
      :indent="20"
      :columns="columns"
      :request-api="getAuthMenuListApi"
      :data-callback="dataCallback"
    >
      <!-- 表格 header 按钮 -->
      <template #tableHeader>
        <el-button type="primary" :icon="CirclePlus" @click="menuOperate('新增')">新增菜单 </el-button>
      </template>
      <!-- 菜单图标 -->
      <template #icon="scope">
        <el-icon :size="18">
          <component :is="scope.row.meta.icon"></component>
        </el-icon>
      </template>
      <!-- 菜单操作 -->
      <template #operation="scope">
        <el-button type="primary" link :icon="CirclePlus" @click="menuOperate('新增子', scope.row)"> 新增子菜单 </el-button>
        <el-button type="warning" link :icon="EditPen" @click="menuOperate('编辑', scope.row)"> 编辑 </el-button>
        <el-button type="danger" link :icon="Delete" @click="menuOperate('删除', scope.row)"> 删除 </el-button>
      </template>
    </ProTable>
    <MenuDialog ref="menuDialogRef"></MenuDialog>
  </div>
</template>

<script setup lang="ts" name="menuMange">
import { ref } from "vue";
import { ColumnProps } from "@/components/ProTable/interface";
import { Delete, EditPen, CirclePlus } from "@element-plus/icons-vue";
import ProTable from "@/components/ProTable/index.vue";
import MenuDialog from "./components/MenuDialog.vue";
import { getAuthMenuListApi } from "@/api/modules/login";
import { ElMessage, ElMessageBox } from "element-plus";

const proTable = ref();
const menuDialogRef = ref<InstanceType<typeof MenuDialog> | null>(null);
const dataCallback = (data: any) => {
  return {
    list: data,
    total: data.total,
    pageNum: data.pageNum,
    pageSize: data.pageSize
  };
};
// 表格配置项
const columns: ColumnProps[] = [
  { prop: "meta.title", label: "菜单名称", align: "left", search: { el: "input" } },
  { prop: "meta.icon", label: "菜单图标" },
  { prop: "name", label: "菜单 name", search: { el: "input" } },
  { prop: "path", label: "菜单路径", width: 300, search: { el: "input" } },
  { prop: "component", label: "组件路径", width: 300 },
  { prop: "operation", label: "操作", width: 300, fixed: "right" }
];
const menuOperate = (title: string, row: Partial<Menu.MenuOptions> = {}) => {
  if (title == "删除") {
    ElMessageBox.confirm(`确认删除菜单 ${row.meta?.title} 及其子菜单`, `删除菜单 ${row.meta?.title} 及其子菜单`, {
      type: "error"
    }).then(() => {
      ElMessage.success("删除成功");
    });
    return;
  }
  const params = {
    title: title == "编辑" ? "编辑" + row.meta?.title : title == "新增子" ? "新增" + row.meta?.title + "子" : title,
    row: title == "新增子" ? {} : { ...row },
    api: () => {
      console.log("操作成功");
    },
    getTableList: proTable.value?.getTableList
  };
  menuDialogRef.value?.acceptParams(params);
};
</script>

最终效果如下

总结

写起来还是非常方便的,刚刚开始可能看不太懂,写了一遍之后就好多了 , 项目中使用ts的范围非常广 , 我之前接触的项目,有一半都懒得给直接any,但是初看下来框架中都给了类型,请求的返回值也给了,有些类型我看不懂,还在学习中。

相关推荐
百万蹄蹄向前冲1 小时前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5812 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路2 小时前
GeoTools 读取影像元数据
前端
ssshooter3 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
Jerry3 小时前
Jetpack Compose 中的状态
前端
dae bal4 小时前
关于RSA和AES加密
前端·vue.js
柳杉4 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化
lynn8570_blog4 小时前
低端设备加载webp ANR
前端·算法
LKAI.5 小时前
传统方式部署(RuoYi-Cloud)微服务
java·linux·前端·后端·微服务·node.js·ruoyi
刺客-Andy5 小时前
React 第七十节 Router中matchRoutes的使用详解及注意事项
前端·javascript·react.js