本文最后更新于 2023-12-16,文章内容可能已经过时,请注意发布时间。


title: vben admin 学习记录(三)
id: 439327e8-926e-4d3b-9ff4-6619e4ecc241
date: 2023-12-11 00:41:25
auther: liqi
excerpt: 前言 本章主要讲一下vben 的表单简单使用以及一些骚操作~ 表单基础 表单高级用法 正文 表单基础 首先,在vben中,表单是通过封装,让他成为组件的一些配置,属性,再将他们。这使得开发人员在熟悉vben后,开发速度会非常快,便捷,减少开发代码量。这一部分,主要分享的就是vben中表单的基本用法。
permalink: /archives/e317606f-c85e-4205-89d3-f398dc42af30
categories:

  • qian-duan
    tags:
  • vue

前言

本章主要讲一下vben 的表单简单使用以及一些骚操作\~

  • 表单基础
  • 表单高级用法

正文

表单基础

首先,在vben中,表单是通过封装,让他成为组件的一些配置,属性,再将他们。这使得开发人员在熟悉vben后,开发速度会非常快,便捷,减少开发代码量。这一部分,主要分享的就是vben中表单的基本用法。对于框架中可以使用的各种属性,可以在Form 表单组件 | Vben Admin 中查看。

弹窗页面的表单

我们要实现在单独页面中让他展示出表格是非常简单的,根据官网给出的示例代码复制就可以用,我们主要分享一下弹窗中如何实现,具体功能我会写在注释中,具体来说,之前有讲过vben在使用弹窗如何给子组件传值\~有什么不懂的,可以去看从0开始学习 vben admin(二) - 掘金 (juejin.cn) 这篇文章。里面的注释中都每步的操作,这里主要说了一下他接值后如何赋值。

html部分:

<template>  
    <div>  
        <!-- 在这里的 @ok方法来监听点击确认按钮-- 这里是弹窗组件 -->  
        <BasicModal  
            v-bind="$attrs"  
            @register="modalInner"  
            title="企业管理 窗口"  
            @ok="addSubmitForm"  
            @visible-change="handleVisibleChange"  
        >  
        <div class="pt-3px pr-3px">  
        <!-- 这里是引用表单组件  -->
        <BasicForm  
            @register="registerForm"  <!-- 将配置好的表单赋值到这个组件中 -->
            :model="model"  
        />  
        </div>  
        </BasicModal>  
    </div>  
</template>

js部分:

<script lang="ts">  
import { defineComponent, ref, nextTick } from 'vue';  
import { BasicModal, useModalInner } from '/@/components/Modal';  
import { BasicForm, useForm } from '/@/components/Form/index';  
import { addEnterprise, updateEnterprise } from '../api/enterprise';  
import { getEnterpriseForm } from '../data/enterpriseform';  

export default defineComponent({  
    components: { BasicModal, BasicForm },  
        props: {  
        userData: { type: Object },  
    },  
    setup(props) {  
        const modelRef = ref({});  
        const isUpdate = ref(false);  
        const id = ref(0);  
        const [modalInner, { closeModal }] = useModalInner((data) => {  
            if (data != null) {  
                isUpdate.value = true;  
            }  
            id.value = data.id;  // 如果是修改的话,给他添加id
            setFieldsValue(data);  // 在声明表单组件的时候要提出这个方法,他的作用的写入表单的值,根据字段名称会自动匹配。
        });  
        const [  
            registerForm,  
            { getFieldsValue, setFieldsValue, resetFields, validate, updateSchema },  
            ] = useForm({  
                labelWidth: 180,  
                schemas: getEnterpriseForm(),  
                showActionButtonGroup: false,  
                actionColOptions: {  
                    span: 24,  
                },  
            });  
        function onDataReceive(data) {  
            console.log('Data Received', data);  
        }  
        // 新增企业管理  
        function addSubmitForm() {  
            // 这里是验证表单必填值  
            validate();  
            // 获取表单中的值  
            let data = getFieldsValue();  
            console.log(data);  
            if (!isUpdate.value) {  
                // 执行添加接口,是在api中封装的接口  
                addEnterprise(data);  
            } else {  
            data.id = id.value;  
            // 执行修改接口,是在api中封装的接口  
            updateEnterprise(data);  
            }  
            // 这个方法是官网的一个重置表单的方法  
            resetFields();  
            isUpdate.value = false;  
            // 关闭弹窗  
            closeModal();  
        }  
        function handleVisibleChange(v) {  
            v && props.userData && nextTick(() => onDataReceive(props.userData));  
        }  
        return {  
            updateSchema,  
            modalInner,  
            registerForm,  
            model: modelRef,  
            handleVisibleChange,  
            addSubmitForm,  
        };  
    },  
});  
</script>

表单一些高级组件

上面那些可以完成一些简单、初级的表单应用场景,如果你想要一些高级一点的用法,vben也是可以满足的,对于这个来说,vben的开发者们都写出了demo,在开发vben的过程中,我个人推荐的用法就是下载两个版本相同的源码,在开发过程中,可以使用开发者给出的demo来帮助自己更加高效的开发,他的路径就是src/views/demo

image.png
可折叠表单
image.png
标签页+多级field表单
image.png

在开发中,你可以根据他的路由来查找demo中的对应文件,比如下面这个路由,我们就可以去找demo下的src/views/demo/form/AdvancedForm.vue来查看源码,然后根据自己项目需要的配置来修改

image.png

image.png

表单高级用法

在一些业务场景,我们接到的需求可能单单的表单组件是满足不了的,所以我们需要让表单和其他组件去搭配,今天我分享表单搭配表格使用,比如我自己正在写的代码生成,如果给的列都是固定的,那么对于使用者来说可能会不太友好,因为使用者需要的字段等等都是不一定的,所以我们要完成下面这个样子的表单,这里是使用了vben中可编辑表格的方法组件,来实现让表格和表单一样,可以编辑、修改,下面我会贴出vben中的代码,来实现这个需求。

image.png

image.png

在下面这个页面中,我们同时使用了一个BasicForm组件和一个PersonTable组件页面,其中,BasicForm是用来记录一些固定的参数,而表格的话,是用来批量添加或者批量更新的,这个表格的组件demo在src/views/demo/table/VxeTable.vue可以找到。

<template>  
    <div class="pt-3px pr-3px">  
        <PageWrapper  
        class="high-form"  
        title="代码生成"  
        content=" 一键生成您的数据库、后端、页面的CURD。"  
        >  
            <Card title="控制器信息" :bordered="false">  
                <BasicForm @register="registerForm" :model="model" @submit="addSubmitForm" />  
            </Card>  
            <Card title="数据库字段信息" :bordered="false">  
                <PersonTable ref="tableRef" />  
            </Card>  
            <template #rightFooter>  
                <Button type="primary" @click="addSubmitForm"> 提交 </Button>  
            </template>  
        </PageWrapper>  
    </div>  
</template>
```ts
<script lang="ts">
  import { defineComponent, ref, nextTick } from 'vue';
  import { BasicForm, useForm } from '/@/components/Form/index';
  import { addCodeGeneration } from './api/codeGeneration';
  import { getDatabaseForm } from './data/codeGenerationform';
  import { Button } from '/@/components/Button';
  import { Card } from 'ant-design-vue';
  import { PageWrapper } from '/@/components/Page';
  import PersonTable from './table/DatabaseTable.vue'; // 引用表格的页面

  export default defineComponent({
    components: { BasicForm, Button, Card, PageWrapper, PersonTable },
    props: {
      userData: { type: Object },
    },
    setup(props) {
      const modelRef = ref({});
      const isUpdate = ref(false);
      const [
        registerForm,
        { appendSchemaByField, removeSchemaByFiled, getFieldsValue, validate, updateSchema },
      ] = useForm({
        labelWidth: 180,
        schemas: getDatabaseForm(),
        showActionButtonGroup: false,
        actionColOptions: {
          span: 24,
        },
      });
      function onDataReceive(data) {
        console.log('Data Received', data);
      }

      const tableRef = ref<{ getDataSource: () => any } | null>(null); // 初始化表格中的值
      // 新增权限
      function addSubmitForm() {
        if (tableRef.value) {
          console.log('table data:', tableRef.value.getDataSource());
        }
        // 这里是验证表单必填值
        validate();
        // 获取表单中的值
        let data = getFieldsValue();
        data.field = tableRef.value.getDataSource();
        console.log(data);
        if (!isUpdate.value) {
          // 执行添加接口,是在api中封装的接口
          addCodeGeneration(data);
        } else {
          // 执行修改接口,是在api中封装的接口
          // updatePermission(data);
          console.log('编辑');
        }
      }
      function handleVisibleChange(v) {
        v && props.userData && nextTick(() => onDataReceive(props.userData));
      }
      return {
        updateSchema,
        registerForm,
        model: modelRef,
        handleVisibleChange,
        addSubmitForm,
        appendSchemaByField,
        removeSchemaByFiled,
        tableRef,
      };
    },
  });
</script>
  • 这里是表格的ts代码
<template>  
    <div>  
        <BasicTable @register="registerTable" @edit-change="handleEditChange">  
            <template #action="{ record, column }">  
            <TableAction :actions="createActions(record, column)" minhight="0" />  
        </template>  
        </BasicTable>  
        <a-button block class="mt-5" type="dashed" @click="handleAdd"> 新增字段 </a-button>  
    </div>  
</template>
```ts
setup() {
      const [registerTable, { getDataSource }] = useTable({
        columns: columns,
        showIndexColumn: false,
        autoCreateKey: false,
        actionColumn: {
          width: 120,
          title: '操作',
          dataIndex: 'action',
          slots: { customRender: 'action' },
        },
        pagination: false,
      });

      function handleEdit(record: EditRecordRow) {
        record.onEdit?.(true);
      }

      function handleCancel(record: EditRecordRow) {
        record.onEdit?.(false);
        if (record.isNew) {
          const data = getDataSource();
          const index = data.findIndex((item) => item.key === record.key);
          data.splice(index, 1);
        }
      }

      function handleSave(record: EditRecordRow) {
        record.onEdit?.(false, true);
      }

      function handleEditChange(data: Recordable) {
        console.log(data);
      }

      function handleAdd() {
        const data = getDataSource();
        const addRow: EditRecordRow = {
          name: '',
          no: '',
          dept: '',
          editable: true,
          isNew: true,
          key: `${Date.now()}`,
        };
        data.push(addRow);
      }

      function createActions(record: EditRecordRow, column: BasicColumn): ActionItem[] {
        if (!record.editable) {
          return [
            {
              label: '编辑',
              onClick: handleEdit.bind(null, record),
            },
            {
              label: '删除',
              popConfirm: {
                title: '是否删除该行?',
                confirm: handleCancel.bind(null, record, column),
              },
            },
            {
              label: '+',
              onClick: handleAdd.bind(null, record),
            },
          ];
        }
        return [
          {
            label: '保存',
            onClick: handleSave.bind(null, record, column),
          },
          {
            label: '取消',
            popConfirm: {
              title: '是否取消编辑并删除该行?',
              confirm: handleCancel.bind(null, record, column),
            },
          },
          {
            label: '+',
            onClick: handleAdd.bind(null, record), // 点击他可以新增一行表格
          },
        ];
      }

      return {
        registerTable,
        handleEdit,
        createActions,
        handleAdd,
        getDataSource,
        handleEditChange,
      };
    },

结尾

结语

在vben框架中,有很多有意思的搭配,可以让我们完成更多的功能,喜欢的朋友们请点赞给点鼓励,可以在评论区说想了解什么,我会尽力满足,今天的分享就到这里了!

下期预告

  • 关于路由