前端提升生产力系列一(vue3 element-plus 配置json快速生成form表单组件)

简介: 在PC端日常的使用中,使用最多的莫过于表单和列表了,故此对table列表和form表单进行了统一的封装,通过json配置就可以快速适配table列表和form表单。

大家好,我是aehyok🎋,一个住在深圳城市的佛系码农🧚🏻‍♀️,如果你喜欢我的文章📚,可以通过点赞帮我聚集灵力⭐️。


个人github仓库地址: https:github.com/aehyok


本文讲解代码仓库地址 :  https:github.com/aehyok/vue-… 目前基于dev分支进行开发和测试


本demo已部署腾讯云 vue.tuokecat.com(服务器配置较低,如有访问比较慢,请耐心等待)


table封装路径为根路径下的 vue-qiankun/common/components/form/


form表单json配置生成器


  • 1、 在PC端日常的使用中,使用最多的莫过于表单和列表了,故此对table列表和form表单进行了统一的封装,通过json配置就可以快速适配table列表和form表单。


  • 2、本章节主要记录自己的form表单封装


  • 3、封装思路


  • A、根据布局,一行一列默认可不设置(columnSpan设置为24),一行两列可设置参数columnSpan设置为12,后续以此类推


  • B、根据不同的字段类型,分别对应子组件进行渲染


  • C、子组件根据不同的类型,以及配置的类型字段进行渲染和数据绑定


  • D、子组件可以设置必填项和rules表单验证规则


  • E、可以通过设置字段的值,去控制其他字段的展示和隐藏


  • F、下拉等字典类型数据,可统一设置读取接口数据,也可以根据需要进行传递当前数组数据


  • G、图片上传可设置上传接口,并可设置上传多张图片


  • H、富文本编辑器也可以作为组件嵌入表单


  • I、 ......


先来一个完整的效果展示


  • 1、form表单配置json


{
  "formListItem": [
    {
      "name": "name1",
      "type": "text",
      "title": "栏目标题",
      "required": true
    },
    {
      "name": "name",
      "type": "text",
      "title": "栏目名称"
    },
    {
      "name": "total",
      "type": "number",
      "title": "栏目数量",
      "required": true
    },
    {
      "name": "count",
      "type": "number",
      "title": "浏览数量"
    },
    {
      "name": "descript",
      "type": "textarea",
      "title": "备注",
      "required": true,
      "rows": 3
    },
    {
      "name": "content",
      "type": "textarea",
      "title": "内容",
      "rows": 3
    },
    {
      "name": "startDate",
      "type": "date",
      "title": "开始日期",
      "required": true
    },
    {
      "name": "endDate",
      "type": "date",
      "title": "结束日期"
    },
    {
      "name": "isValid",
      "type": "switch",
      "title": "是否有效"
    },
    {
      "name": "isExpired",
      "type": "switch",
      "title": "是否过期",
      "required": true
    },
    {
      "name": "type",
      "type": "radio",
      "dictionary": [
        {
          "code": 1,
          "name": "横版栏目"
        },
        {
          "code": 2,
          "name": "竖版栏目"
        }
      ],
      "title": "栏目类型",
      "controls": [
        {
          "value": 1,
          "showCondition": [
            {
              "name": "show",
              "type": "radio",
              "dictionary": [
                {
                  "code": 1,
                  "name": "China"
                },
                {
                  "code": 2,
                  "name": "English"
                }
              ],
              "title": "测试类型",
              "required": true
            },
            {
              "name": "image1",
              "type": "ImageTypeView",
              "title": "文件"
            }
          ]
        },
        {
          "value": 2,
          "showCondition": [
            {
              "name": "isValids",
              "type": "switch",
              "title": "是否有效"
            }
          ]
        }
      ]
    },
    {
      "name": "requireType",
      "type": "radio",
      "dictionary": [
        {
          "code": 1,
          "name": "类型一"
        },
        {
          "code": 2,
          "name": "类型二"
        }
      ],
      "title": "图文类型",
      "required": true
    },
    {
      "name": "range",
      "type": "checkbox",
      "title": "发布范围",
      "dictionary": [
        {
          "code": 1,
          "name": "范围一"
        },
        {
          "code": 2,
          "name": "范围二"
        }
      ],
      "required": true
    },
    {
      "name": "dateRange",
      "type": "daterange",
      "title": "日期范围"
    },
    {
      "name": "creType",
      "type": "select",
      "dictionary": [
        {
          "code": 1,
          "name": "身份证"
        },
        {
          "code": 2,
          "name": "居住证"
        }
      ],
      "title": "证件类型"
    },
    {
      "name": "image",
      "type": "image",
      "title": "头像"
    }
  ],
  "formData": {
    "name": "主菜单栏目",
    "total": null,
    "count": null,
    "createDate": 1606730360386,
    "type": 1,
    "creType": "",
    "range": [],
    "isExpired": false,
    "isValid": true
  }
}


  • 2、 最后的效果图片


image.png


效果展示的在线预览页面为 vue.tuokecat.com/#/webpack-a…


具体代码可根据路由进行搜索


字段配置详细介绍


1、静态文本 static


```javascript
  {
    type: "static",  // 字段类型只读文本
    name: "name",   //与后台对接字段
    title: "名称",  // 前端展示字段
  },
```


2、文本框 text


```javascript
  {
    type: "text",  // 字段类型文本框
    name: "name",  //与后台对接字段
    title: "域名",  // 前端展示字段
    required: true, // 必填项设置
    maxlength: 50,  // 字符串长度限制
    showwordlimit: true, // 是否显示字符串长度
    placeholder:"请输入10个字符以内的名称", // 占位文本提示
    append: ".com",  // 文本框后置内容
    // rules // 数组
    rules: [
      { pattern: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/, message: '请输入数字最多两位小数' }
    ],
  },
```


3、文本域 textarea


```javascript
  {
    type: "textarea",  // 字段类型文本域
    name: "name",  //与后台对接字段
    title: "备注",  // 前端展示字段
    required: true, // 必填项设置
    placeholder:"请输入10个字符以内的名称", // 占位文本提示
    rows: 4, //  输入框行数
    minlength: 100, // 最小输入长度
    maxlength: 5000,  // 最大输入长度
    showwordlimit: true, // 是否显示字符串长度
    // rules // 数组
    rules: [
      { pattern: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/, message: '请输入数字最多两位小数' }
    ],
  },
```


4、下拉框 select


```javascript
  {
    type: "select",  // 字段类型下拉框
    name: "options",   //与后台对接字段
    title: "类型",  // 前端展示字段
    required: true, // 必填项设置
    placeholder:"请选择类型",  // 占位文本提示
    // dictionary  可直接传递下拉数据,也可以传递字典中的typeCode,通过内部接口获取
    dictionary: 7010, // 7010为字典中维护的typecode
    dictionary:[
      {
        code: 1, name:"图片",
      },
      {
        code: 2, name:"视频"
      }
    ],
    multiple: true, // 下拉列表可以多选
    // rules // 正则匹配
    rules: [
      { pattern: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/, message: '只能选择*******' }
    ],
    // 点击下来触发切换联动的事件,为一个函数
    changeFunction: function(){}
  },
```


5、富文本 editor


```javascript
  {
    type: "editor",  // 字段类型富文本
    name: "content",   //与后台对接字段
    title: "内容",  // 前端展示字段
    required: true, // 必填项设置
    placeholder:"请选择类型",  // 占位文本提示
    // rules // 正则匹配
    rules: [
      { pattern: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/, message: '只能选择*******' }
    ],
    maxLength:5000, // 富文本框最大长度,默认5000
  },
```


6、数值框 number


```javascript
  {
    type: "number",  // 字段类型数值
    name: "num",  //与后台对接字段
    title: "总数",  // 前端展示字段
    required: true, // 必填项设置
    placeholder:"请输入10个字符以内的名称", // 占位文本提示
    precision: 2,  // 小数点后的位数
    // rules // 数组
    rules: [
      { pattern: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/, message: '请输入数字最多两位小数' }
    ],
  },
```


7、省市区三级级联选择 citySelect


```javascript
  {
    type: "citySelect",  // 字段类型省市区
    name: "region",  //与后台对接字段
    title: "户籍地",  // 前端展示字段
    required: true, // 必填项设置
    placeholder:"请输入10个字符以内的名称", // 占位文本提示
    // rules // 数组
    rules: [
      { pattern: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/, message: '请输入数字最多两位小数' }
    ],
  },
```   


8、 图片上传 image


```javascript
  {
    type: "image",  // 字段类型图片
    name: "images",  //与后台对接字段
    title: "上传图片",  // 前端展示字段
    required: true, // 必填项设置
    placeholder:"请上传图片", // 占位文本提示
    // rules // 数组
    rules: [
      { pattern: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/, message: '请输入数字最多两位小数' }
    ],
  },
```      


9、 视频上传 video


```javascript
  {
    type: "video",  // 字段类型视频
    name: "images",  //与后台对接字段
    title: "上传视频",  // 前端展示字段
    required: true, // 必填项设置
    placeholder:"请上传视频", // 占位文本提示
    // rules // 数组
    rules: [
      { pattern: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/, message: '请输入数字最多两位小数' }
    ],
  },
```      


10、 日期 date


```javascript
  {
    type: "date",  // 字段类型日期
    name: "date",  //与后台对接字段
    title: "日期",  // 前端展示字段
    required: true, // 必填项设置
    placeholder:"请选择日期", // 占位文本提示
    // rules // 数组
    rules: [
      { pattern: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/, message: '请输入数字最多两位小数' }
    ],
  },
```      


11、 日期范围 daterange


```javascript
  {
    type: "daterange",  // 字段类型日期
    name: "date",  //与后台对接字段
    title: "日期范围",  // 前端展示字段
    required: true, // 必填项设置
    placeholder:"请选择日期", // 占位文本提示
    // rules // 数组
    rules: [
      { pattern: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/, message: '请输入数字最多两位小数' }
    ],
  },
```  


附上整个调用的所有代码


  • 1、template 模板代码


<template>
    <div>
      <sl-table
        :list="list"
        @handleSelectionChange="handleSelectionChange"
        :columns="columns"
        :operates="operates"
        v-model:pageModel="pageModel"
        @search="search"
      >
      </sl-table>
    </div>
  </template>


  • 2、'script'标签代码


import SlTable from '../../../common/components/table/index.vue'
import { defineComponent, reactive, toRefs } from "vue";
import { list_test, columns_test } from "./tableConfig";
export default defineComponent({
components: { SlTable },
setup() {
  // 选中行
  const handleSelectionChange = (val) => {
    console.log("handleSelectionChange-val:", val);
  };
  // 编辑
  const handleDetail = (index, row, idx) => {
    console.log("index:", index, idx);
    console.log("row:", row);
  };
  // 删除
  const handleDel = (index, row) => {
    console.log(" index:", index);
    console.log(" row:", row);
  };
  const state = reactive({
    pageModel: {
      page: 1,
      limit: 10,
      total: 17
    },
    list: [], // table数据
    columns: [], // 需要展示的列
    operates: {
      width: 200,
      fixed: "right",
      list: [
        {
          id: "1",
          label: "查看",
          type: "text",
          show: true,
          disabled: false,
          method: (index, row, ss) => {
            handleDetail(index, row, ss);
          }
        },
        {
          id: "2",
          label: "删除",
          type: "text",
          show: true,
          disabled: false,
          method: (index, row) => {
            handleDel(index, row);
          }
        }
      ]
    } // 列操作按钮
  });
  state.list = list_test;
  state.columns = columns_test;
  const search = () => {
    state.list = [...state.list];
    console.log(state.pageModel, "state.pageModel");
  };
  return {
    ...toRefs(state),
    handleSelectionChange,
    search
  };
}
});


  • 3、其中模拟数据和字段配置在单独的文件中tableConfig


const list_test =
[
  {
      id: "24",
      title: "编号3",
      state: 0,
      createTime:"2021-09-23T17:57:09",
      remark: "自定义"
  },
  {
      id: "23",
      title: "编号4",
      state: 1,
      createTime:"2021-09-23T17:57:19",
      remark: "自定义"
  },
  {
      id: "23",
      title: "编号5",
      state: 2,
      createTime:"2021-09-23T17:57:29",
      remark: "自定义"
  },
  {
     id: "23",
     title: "编号5",
     state: 1,
     createTime:"2021-09-23T17:57:39",
     remark: "自定义111"
  },
  {
      id: "223",
      title: "编号3",
      state: 1,
      createTime:"2021-09-23T17:57:49",
      remark: "22222"
  },
  {
      id: "2444",
      title: "编号3",
      state: 0,
      createTime:"2021-09-23T17:57:59",
      remark: "333333"
  },
  {
    id: "24",
    title: "编号3",
    state: 0,
    createTime:"2021-09-23T17:57:09",
    remark: "自定义"
},
{
    id: "23",
    title: "编号4",
    state: 1,
    createTime:"2021-09-23T17:57:19",
    remark: "自定义"
},
{
    id: "23",
    title: "编号5",
    state: 2,
    createTime:"2021-09-23T17:57:29",
    remark: "自定义"
},
{
   id: "23",
   title: "编号5",
   state: 1,
   createTime:"2021-09-23T17:57:39",
   remark: "自定义111"
},
{
    id: "223",
    title: "编号3",
    state: 1,
    createTime:"2021-09-23T17:57:49",
    remark: "22222"
},
{
    id: "2444",
    title: "编号3",
    state: 0,
    createTime:"2021-09-23T17:57:59",
    remark: "333333"
}
]
const columns_test = [
  {
      type:'checkbox',
  },
  {
    prop: "id",
    label: "编号",
    type:'index',
    align: "center"
  },
  {
    prop: "title",
    label: "标题",
    align: "center",
  },
  {
    prop: "createTime",
    label: "创建时间",
    align: "center",
    dateFormat: "yyyy-MM-dd HH:mm:ss",
    sortable: true
  },
  {
    prop: "state",
    label: "状态",
    align: "center",
    dictionary: [
      { code: 0, name: "待审核"},
      { code: 1, name: "已审核"},
      { code: 2, name: "审核中"},
    ]
  },
  {
    prop:"custom",
    label:"自定义",
    align: "center",
    html: (row, column) => {
      return row.title==="编号3" ? `<span style="color: red;">${ row.remark }</span>`:`未定义`
    }
  }
]
export {
  list_test,
  columns_test
}


最后的最后


github.com/aehyok/vue-…本文中不涉及到代码,有关代码问题可以访问文章开头的微前端github demo 仓库,github仓库将会保持持续更新,不断优化小demo。


github.com/aehyok/2021最后自己每天工作中的笔记记录仓库,主要以文章链接和问题处理方案为主。

目录
相关文章
|
5天前
|
JavaScript 前端开发
如何在 Vue 项目中配置 Tree Shaking?
通过以上针对 Webpack 或 Rollup 的配置方法,就可以在 Vue 项目中有效地启用 Tree Shaking,从而优化项目的打包体积,提高项目的性能和加载速度。在实际配置过程中,需要根据项目的具体情况和需求,对配置进行适当的调整和优化。
|
6天前
|
存储 JavaScript 开发者
Vue 组件间通信的最佳实践
本文总结了 Vue.js 中组件间通信的多种方法,包括 props、事件、Vuex 状态管理等,帮助开发者选择最适合项目需求的通信方式,提高开发效率和代码可维护性。
|
6天前
|
存储 JavaScript
Vue 组件间如何通信
Vue组件间通信是指在Vue应用中,不同组件之间传递数据和事件的方法。常用的方式有:props、自定义事件、$emit、$attrs、$refs、provide/inject、Vuex等。掌握这些方法可以实现父子组件、兄弟组件及跨级组件间的高效通信。
|
17天前
|
JavaScript 前端开发 开发者
如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 检查代码规范并自动格式化 Vue.js 代码,包括安装插件、配置 ESLint 和 Prettier 以及 VSCode 设置的具体步骤
随着前端开发技术的快速发展,代码规范和格式化工具变得尤为重要。本文介绍了如何在 Visual Studio Code (VSCode) 中使用 ESLint 和 Prettier 检查代码规范并自动格式化 Vue.js 代码,包括安装插件、配置 ESLint 和 Prettier 以及 VSCode 设置的具体步骤。通过这些工具,可以显著提升编码效率和代码质量。
174 4
|
18天前
|
缓存 JavaScript UED
Vue 中实现组件的懒加载
【10月更文挑战第23天】组件的懒加载是 Vue 应用中提高性能的重要手段之一。通过合理运用动态导入、路由配置等方式,可以实现组件的按需加载,减少资源浪费,提高应用的响应速度和用户体验。在实际应用中,需要根据具体情况选择合适的懒加载方式,并结合性能优化的其他措施,以打造更高效、更优质的 Vue 应用。
|
19天前
|
前端开发 JavaScript 开发者
揭秘前端高手的秘密武器:深度解析递归组件与动态组件的奥妙,让你代码效率翻倍!
【10月更文挑战第23天】在Web开发中,组件化已成为主流。本文深入探讨了递归组件与动态组件的概念、应用及实现方式。递归组件通过在组件内部调用自身,适用于处理层级结构数据,如菜单和树形控件。动态组件则根据数据变化动态切换组件显示,适用于不同业务逻辑下的组件展示。通过示例,展示了这两种组件的实现方法及其在实际开发中的应用价值。
27 1
|
21天前
|
资源调度 JavaScript 前端开发
路由管理:Vue Router的使用和配置技巧
【10月更文挑战第21天】路由管理:Vue Router的使用和配置技巧
30 3
|
22天前
|
前端开发 UED
vue3知识点:Suspense组件
vue3知识点:Suspense组件
30 4
|
21天前
|
JavaScript 前端开发 测试技术
组件化开发:创建可重用的Vue组件
【10月更文挑战第21天】组件化开发:创建可重用的Vue组件
24 1
|
22天前
|
JavaScript 前端开发 Java
《vue3第五章》新的组件,包含:Fragment、Teleport、Suspense
《vue3第五章》新的组件,包含:Fragment、Teleport、Suspense
32 2