vue3 element-plus 配置json快速生成form表單元件,提升生產力近600%(已在公司使用,持續優化中)

語言: CN / TW / HK

:warning:本文為部落格園社群首發文章,未獲授權禁止轉載

大家好,我是aehyok:tanabata_tree:,一個住在深圳城市的佛系碼農 ‍♀️,如果你喜歡我的文章:books:,可以通過點贊幫我聚集靈力:star:️。

個人github倉庫地址: https:github.com/aehyok

本文講解程式碼倉庫地址 : https:github.com/aehyok/vue-qiankun 目前基於dev分支進行開發和測試

本demo已部署騰訊雲 http://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、 最後的效果圖片

效果展示的線上預覽頁面為 http://vue.tuokecat.com/#/webpack-app/form

具體程式碼可根據路由進行搜尋

欄位配置詳細介紹

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
}

最後的最後

https://github.com/aehyok/vue-qiankun

本文中不涉及到程式碼,有關程式碼問題可以訪問文章開頭的微前端github demo 倉庫,github倉庫將會保持持續更新,不斷優化小demo。

https://github.com/aehyok/2021

最後自己每天工作中的筆記記錄倉庫,主要以文章連結和問題處理方案為主。