element 封装配置试输入框组件(复用性极高)

146 阅读2分钟

该项目git地址

  • 结合项目源码更容易看懂 代码更完整

随便扯扯

  • 以前做项目的过程中呢 发现封装组件能够提高开发效率并且降低耦合度

  • 也在这里踩了很多坑 由刚开始的只能父子组件传值 到抽离出一个比较通用的公共组件

    • 也极大的提高了开发效率
  • 这里也是学习到了一种极具通用性的组件开发方式 也在此做一个记录 进行分享

  • 也算是对之前的学习内容进行一个总结和巩固吧

element 配置式 组建的封装

  • 之前在做一个项目的时候 有一个需求 使用 element 需要获取一个输入的信息 但是这个这种获取输入页面有很多相似的 于是就开始捣鼓怎么把他抽离成一个公共组件 在一直优化的过程中了解到了这种配置式的封装 yysy 真滴好用

  • 话不多说 先看效果

  • image.png

  • 思路

    • 因为使用的是 element

      • 1.使用 其中的布局 Layout 可以实现传参控制布局 与配置式十分契合
      • 2.其中的 各个组件的宽度也有参数可以进行配置
      • 3.其中各种 表单组件可以通过 type 传递参数控制 那么就可以配置不同的 表单组件
      • 4.使用一个 for 循环将配置的参数直接传递进去就行了

代码 里面有注释

  • image.png

  • 里面使用了 ts 进行类型限制 这个关系不大

  • 组件代码

    • <template>
        <div class="hy-form">
          <div class="header">
            <slot name="header"></slot>
          </div>
          <!-- 使用 from 表单收集信息 -->
          <el-form :label-width="props.labelWidth">
            <el-row>
              <!-- 遍历配置信息 -->
              <template v-for="item in props.formItems" :key="item.label">
                <el-col v-bind="colLayout">
                  <el-form-item
                    :label="item.label"
                    :rules="item.rules"
                    :style="props.itemStyle"
                  >
                    <!-- 输入框 -->
                    <template
                      v-if="item.type === 'input' || item.type === 'password'"
                    >
                      <el-input
                        v-bind="item.otherOptions"
                        v-model="formData[`${item.field}`]"
                        :placeholder="item.placeholder"
                        :show-password="item.type === 'password'"
                      />
                    </template>
                    <!-- 选择框 -->
                    <template v-else-if="item.type === 'select'">
                      <el-select
                        v-bind="item.otherOptions"
                        v-model="formData[`${item.field}`]"
                        :placeholder="item.placeholder"
                        style="width: 100%"
                      >
                        <el-option
                          v-for="option in item.options"
                          :key="option.value"
                          :value="option.value"
                          >{{ option.title }}</el-option
                        >
                      </el-select>
                    </template>
                    <!-- 日期框 -->
                    <template v-else-if="item.type === 'datepicker'">
                      <el-date-picker
                        v-bind="item.otherOptions"
                        v-model="formData[`${item.field}`]"
                        style="width: 100%"
                      ></el-date-picker>
                    </template>
                  </el-form-item>
                </el-col>
              </template>
            </el-row>
          </el-form>
          <div class="footer">
            <slot name="footer"></slot>
          </div>
        </div>
      </template><script setup lang="ts">
      import { defineProps, defineEmits, PropType, ref, watch } from 'vue'
      import { IFormItem } from '../types'// 传递过来配置的参数就行
      const props = defineProps({
        modelValue: {
          type: Object,
          required: true,
        },
        formItems: {
          type: Array as PropType<IFormItem[]>,
          // 传值的时候 如果是数组或者对象 一定要使用箭头函数来做默认值
          // 就是要用一个函数使用 return 返回 箭头函数时简写 但是因为 this 的原因 箭头函数会更好用
          default: () => [],
        },
        // 设置输入框左边字体的宽度
        labelWidth: {
          type: String,
          default: '100px',
        },
        itemStyle: {
          type: Object,
          default: () => ({ padding: '10px 40px' }),
        },
        // 响应式的布局参数
        // span 的话 默认 24 份 设置为 8 就是一行分三份
        colLayout: {
          type: Object,
          default: () => ({
            xl: 6, // >1920px 4个
            lg: 8,
            md: 12,
            sm: 24,
            xs: 24,
          }),
        },
      })
      ​
      const emit = defineEmits(['update:modelValue'])
      const formData = ref({ ...props.modelValue })
      watch(
        formData,
        (newValue) => {
          console.log(newValue)
          emit('update:modelValue', newValue)
        },
        {
          deep: true,
        }
      )
      </script><style scoped lang="less">
      .hy-form {
        padding-top: 22px;
      }
      </style>
      
    • 父子组件传参的下一篇讲 这里踩了挺多坑的 主要是获取子组件 输入框中的值 父子组件是双向绑定的 说多了都是泪啊
  • 父组件的配置

    • export const searchFormConfig: IForm = {
        labelWidth: '100px',
        itemLayout: {
          padding: '10px 10px',
        },
        colLayout: {
          span: 8,
        },
        formItems: [
          {
            field: 'id',
            type: 'input',
            label: 'id',
            placeholder: '请输入id',
          },
          {
            field: 'name',
            type: 'input',
            label: '用户名',
            placeholder: '请输入用户名',
          },
          {
            field: 'password',
            type: 'password',
            label: '密码',
            placeholder: '请输入密码',
          },
          {
            field: 'sport',
            type: 'select',
            label: '喜欢的运动',
            placeholder: '请选择喜欢的运动',
            options: [
              { title: '篮球', value: 'basketball' },
              { title: '足球', value: 'football' },
            ],
          },
          {
            field: 'createTime',
            type: 'datepicker',
            label: '创建时间',
            otherOptions: {
              startPlaceholder: '开始时间',
              endPlaceholder: '结束时间',
              type: 'daterange',
            },
          },
        ],
      }
      
  • 先这样吧 以后看看补充详细点