IMAGINE'S BLOG IMAGINE'S BLOG
首页
  • 原生JS

    • JavaScript
  • 前端框架扩展

    • Vue
    • React
    • UI组件库
  • HTML
  • CSS
  • 浏览器
  • 分类
  • 标签
  • 归档
  • 技术文档
  • GitHub相关
  • Nodejs
关于
  • 网站
  • 友情链接
GitHub (opens new window)

peng

平平无奇的web前端开发一枚
首页
  • 原生JS

    • JavaScript
  • 前端框架扩展

    • Vue
    • React
    • UI组件库
  • HTML
  • CSS
  • 浏览器
  • 分类
  • 标签
  • 归档
  • 技术文档
  • GitHub相关
  • Nodejs
关于
  • 网站
  • 友情链接
GitHub (opens new window)
  • Element-UI问题清单
  • el-form表单封装
    • 缘由
    • 结构
    • 开始
    • 使用
  • 解决element表格数据量过大导致页面渲染缓慢、卡顿问题
  • UI组件库
peng
2022-09-06
目录

el-form表单封装

# 缘由

系统页面大部分为form+tabel的结构,系统复杂起来代码就看起来非常冗余,要修改起来也很麻烦,于是决定将表单封装起来。

# 结构

  1. 业务与逻辑区分

    • 新建const.js文件,处理表单逻辑
  2. 配置化

    • json对象化配置表单属性
  3. 扩展&特殊处理

    • 配置slot插槽

# 开始

<template>
  <el-form
    ref="form"
    :id="formConfig.id"
    :class="formConfig.className"
    :label-width="formConfig.labelWidth || '100px'"
    :size="formConfig.size || 'medium'"
    :rules="formConfig.rules"
    :model="formData"
  >
      <template
        v-for="(item, index) in getConfigList()"
        :key="index"
      >
        <el-form-item
          :prop="item.value"
          :label="item.label"
          :label-width="item.labelWidth"
          :class="item.className"
        >
          <!-- solt -->
          <template v-if="item.type === 'slot'">
            <slot :name="'form-' + item.value" />
          </template>
          <component
            :is="item.type"
            v-model="formData[item.value]"
            :type="item.dataType"
            :picker-options="item.timePickerOptions"
            :clearable="item.clearable"
            :disabled="item.disabled"
            :start-placeholder="item.startPlaceholder"
            :end-placeholder="item.endPlaceholder"
            :range-separator="item.rangeSeparator || '-'"
            :filterable="item.filterable"
            :multiple="item.multiple"
            :collapse-tags="item.collapseTags"
            default-first-option
            :allow-create="item.allowCreate"
            :no-data-text="item.noDataText || ''"
            :placeholder="getPlaceholder(item)"
            :value-format="item.valueFormat"
            :format="item.valueFormat"
            :style="{ width: item.width || '100%' }"
            :maxlength="item.maxLength"
            :autosize="item.autosize || { minRows: 2, maxRows: 10 }"
            @click="handleEvent(item.event, formData[item.value], 'click')"
            @change="handleEvent(item.event, formData[item.value], 'change')"
            @input="handleEvent(item.event, formData[item.value], 'input')"
            @blur="handleEvent(item.event, formData[item.value], 'blur')"
          >
            <template v-if="item.type === 'el-select'">
              <el-option
                v-for="(childItem, childIndex) in listTypeInfo[item.list]"
                :key="`${childItem.value}${childIndex}`"
                :label="childItem.label"
                :value="childItem.value"
              ></el-option>
            </template>
            {{ item.title || '' }}
          </component>
        </el-form-item>
   </template>
  </el-form>
</template>
<script>

export default {
  name: 'FormItemComp',
  data() {
    return { formData: {} };
  },
  props: {
    // 表单配置项
    formConfig: {
      type: Object,
      default: () => {},
    },
    // 表单数据
    data: { type: Object },
    // 下拉选项list
    listTypeInfo: { type: Object },
    // ref
    refObj: { type: Object },
  },
  watch: {
    data: {
      handler(val) {
        if (!val) return;
        this.formData = val;
        // 将form实例返回到父级
        this.$emit('update:refObj', this.$refs.form);
      },
      deep: true,
    },
  },
  mounted() {
    this.formData = this.data;
    // 将form实例返回到父级
    this.$emit('update:refObj', this.$refs.form);
  },
  methods: {
    // 获取字段列表
    getConfigList() {
      return this.formConfig.fieldList.filter(
        (item) => !Object.prototype.hasOwnProperty.call(item, 'show')
          || (Object.prototype.hasOwnProperty.call(item, 'show') && item.show),
      );
    },
    // 得到placeholder的显示
    getPlaceholder(row) {
      let placeholder;
      const types = ['el-select', 'el-date-picker'];
      if (row.type === 'el-input') {
        placeholder = `请输入${row.placeholder || ''}`;
      } else if (types.includes(row.type)) {
        placeholder = `请选择${row.placeholder || ''}`;
      } else {
        placeholder = row.label;
      }
      return placeholder;
    },
    // 表单事件派发
    handleEvent(event, data, type) {
      this.$emit('handleEvent', { event, data, type });
    },
  },
};
</script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

# 使用

// const.js
export const FormJson =  {
  id: 'form',
  rules: {},
  labelWidth: '100px',
  size: 'mini',
  className: 'el-form-component',
  fieldList: [
    {
      label: '名称:',
      value: 'name',
      type: 'el-select',
      clearable: true,
      list: 'nameList',
    },
    {
      label: '来源:',
      value: 'source',
      type: 'el-select',
      clearable: true,
      list: 'formSelect1',
    },
    {
      label: '主体:',
      value: 'subject',
      type: 'el-input',
    },
    {
      label: '分类:',
      value: 'nature',
      type: 'el-select',
      clearable: true,
      list: 'formSelect2',
    },
    {
      label: '日期:',
      value: 'date',
      type: 'el-date-picker',
      dataType: 'daterange',
      valueFormat: 'yyyy-MM-dd',
      startPlaceholder: '开始日期',
      endPlaceholder: '结束日期',
      rangeSeparator: '至',
      clearable: true,
    },
    {
      label: '状态:',
      value: 'status',
      type: 'el-select',
      clearable: true,
      list: 'projectStatus',
    },
    // slot插槽
    {
      label: '',
      value: 'btn',
      type: 'slot',
      colWidth: 18,
      className: 'text-right',
    },
  ],
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<template>
    <FormItemComp
        :formConfig="FormJson"
        :refObj.sync="formRef"
        :data="formData"
        :listTypeInfo="listTypeInfo"
        @handleEvent="handleEvent"
    >
    <template slot="form-btn">
        <div>
            <el-button type="search" @click="">查询</el-button>
            <el-button type="reset" @click="">重置</el-button>
        </div>
    </template>
    </FormItemComp>
</template>

<script>
import FormItemComp from './FormItemComp'
import { FormJson } from './const.js'
export default {
    data(){
        return {
            FormJson,
            formRef: null, // form ref
            formData: {
                name: '',
                source: '',
                subject: '',
                nature: '',
                date: '',
                status: '',
            },
            // el-select选项
            listTypeInfo: {
                formSelect1:[],
                formSelect2:[],
                projectStatus:[],
                nameList:[],
            }

        }
    },
    components: { FormItemComp },

    methods: {
    // 表单的相关事件
    handleEvent(val) {

    }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#Element-UI#Vue
上次更新: 2022/09/06, 16:01:35
Element-UI问题清单
解决element表格数据量过大导致页面渲染缓慢、卡顿问题

← Element-UI问题清单 解决element表格数据量过大导致页面渲染缓慢、卡顿问题→

最近更新
01
Axios 封装
09-06
02
MySQL数据库常用操作
09-06
03
解决element表格数据量过大导致页面渲染缓慢、卡顿问题
09-06
更多文章>
Theme by Vdoing | Copyright © 2020-2024 peng | IMAGINE
image | imgloc.com
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式