我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Vue2ElementSchemaForm配置式生成表单的实现

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Vue2ElementSchemaForm配置式生成表单的实现

前置知识点

为了实现一个Schema Form配置式表单的生成,需要了解一部分前置知识点。

Component

vue 提供了一个内置组件 Component,用来动态渲染组件,举个例子,本篇文章以Element UI 为例,假设我们全局注册了Element UI的组件,那么下面一段代码

<Component is="el-input"></Component>

将被渲染为el-input组件。

好了,最重要的实现知识点已经完了,只要了解了这一点,我这个Schema Form的实现思路,你就能完全看懂了,就这么简单。

但是为了我们表单的易用性,我们再了解一点儿其他的。

比如Component组件并非只能接收一个字符串,渲染全局组件,同时可以接收一个Component组件,也就是说,当我们Element UI 组件没有全局注册的时候,我们可以通过import { ElInput } from 'element',传递给Component组件,同样可以完成渲染一个el-input组件的功能。

$attrs

第二个知识点,vue属性透传,假如你有这么一个疑惑 —— 我对el-input进行了二次封装,那el-input接收的props我是否需要在二次封装的组件中进行props的定义,再逐一传递给el-input才能生效。

如果有这样的疑惑那么$attrs可以帮你,对于二次封装的组件,通过定义v-bind="$attrs",传递给父组件的属性即可透传给el-input,于是就有了这么一个疑问,$attrs可以绑定给v-bind,那么一个普通的对象可以吗,答案是可以的。

这是我们 schema form 变得好用的第二个重要的知识点。

$listeners

$attrs 相同,做事件透传的,通过v-on绑定。

以上就是我认为,实现Schema Form配置式生成表单所需要掌握的全部知识及扩展思考,接下来,我们简单完成一个配置式表单.

表单的结构是什么样的

1、我可能希望对表单进行一部分特殊的处理,所以,包一层div总是没错的,当然,这是我的习惯,你们可以自行选择。

2、既然是表单,那一定被el-form包裹。

3、为了配置式布局的需要,我希望引入el-row el-col栅格系统

4、无论如何完善表单,必然不可能满足所有要求,那最简单的方式就是抛出slot

5、有些时候我希望渲染文本呢?有些时候我希望渲染字段的值而不涉及任何组件呢?

6、最后才是渲染对应的组件

那么,一个表单的结构化雏形就完成了。

<div class="schema-form">
    <el-form>
        <el-row>
            <el-col v-for="item in config" :key="item.key">
                <el-form-item>
                    <slot v-if="item.component === 'slot'" :name="item.slotName"></slot>
                    <div v-else-if="item.component === 'innerText'"></div>
                    <template v-else>
                        渲染对应组件,但需要对某些组件特殊处理
                    </template>
                </el-form-item>
            </el-col>
        </el-row>
    </el-form>
</div>

从上面的结构中,我们再来思考,我们的配置config数组的字段结构应该是什么样的。

配置数组数据结构

1、el-form 可能需要一些字段注入,作为最外层的组件,将传入schema form的字段都给它

2、el-form 需要传入一个数据源,这个数据源可以内部定义再传给外部,也可以传入一个对象,利用对象的特性做双向绑定,我选择了后者

3、el-col项可能有时不显示,所以config上扩展一个字段hidden,用于控制该项是否显示。

4、el-form-item的属性透传

5、innerText的样式定义

一些特殊的描述出来了,其余的再赘述,那么,config的数据结构就是这样

{
    key: '', // 当前字段的 key 值,同时会传到 el-form-item 的prop,不传数据验证和重置会失效
    label: '', // 当前 el-form-item 的label
    hidden: '', // 当前表单项是否展示
    labelWidth: '', // el-form-item 的label宽度
    component: '', // 支持 slot、innerText、Component,渲染成什么
    slotName: '', // compoment 为 slot 时,该值为对应slot的名字供外部使用
    innerClass: '', // component 为 innerText 时,给文本的样式,通常为全局样式
    innerStyle: '', // 同上
    innerText: '', // component 为 innerText 时,优先显示的文本,否则会显示当前的字段值
    itemProps: '', // 注入到 el-form-item 的属性
    props: '', // 当 component 为渲染组件时,注入到渲染组件当中的属性
    listeners: '', // 当 component 为渲染组件时,注入到渲染组件当中的事件
}

当把这些实现之后,其余需要扩展的功能可以自行实现,我这里也只是在业务中的扩展,并非完善的。

于是,我们的表单组件就变成了这样

<template>
  <div class="nx-form">
    <el-form
      ref="form"
      v-bind="$attrs"
      :model="source"
      class="nx-form"
    >
      <el-row :gutter="20">
        <el-col
          v-for="item in config"
          :key="item.key"
          :span="item.hidden ? 0 : item.span || 8"
        >
          <el-form-item
            v-if="!item.hidden"
            :label="item.label"
            :prop="item.key"
            :label-width="item.labelWidth || labelWidth || '120px'"
            v-bind="item.itemProps"
          >
            <slot v-if="item.component === 'slot'" :name="item.slotName"></slot>
            <div
              v-else-if="item.component === 'innerText'"
              :class="item.innerClass"
              :style="item.style"
            >
              {{ item.innerText || source[item.key] }}
            </div>
            <template v-else>
              <div class="nx-flex-align-center">
                <component
                  :is="item.component"
                  v-model="source[item.key]"
                  style="width: 100%;flex: 1;"
                  v-bind="item.props"
                  v-on="item.listeners"
                >
                  <template v-if="item.component === 'el-radio-group'">
                    <el-radio
                      v-for="(radio, radioIndex) in item.data"
                      :key="radioIndex"
                      style="margin-top: 10px;"
                      :label="radio.value"
                      :disabled="radio.disabled"
                    >
                      {{ radio.label }}
                    </el-radio>
                  </template>

                  <template v-if="item.component === 'el-checkbox-group'">
                    <el-checkbox
                      v-for="(checkbox, checkboxIndex) in item.data"
                      :key="checkboxIndex"
                      :label="checkbox.value"
                    >
                      {{ checkbox.label }}
                    </el-checkbox>
                  </template>

                  <template v-if="item.component === 'el-select'">
                    <el-option
                      v-for="(option, optionIndex) in item.data"
                      :key="optionIndex"
                      :label="option.label"
                      :value="option.value"
                    ></el-option>
                  </template>
                </component>
                <div
                  v-if="item.after"
                  class="nx-form__after"
                >
                  {{ item.after }}
                </div>
              </div>
              <div
                v-if="item.tips"
                class="nx-form__tips"
                v-html="item.tips"
              ></div>
            </template>

          </el-form-item>
          <!-- <div
            v-if="item.tips"
            :style="{ marginLeft: item.labelWidth || '120px' }"
            class="nx-form__tips"
            v-html="item.tips"
          ></div> -->
        </el-col>
      </el-row>
    </el-form>
  </div>
</template>
export default {
  name: 'NxForm',
  components: {},
  props: {
    config: {
      type: Array,
      default: () => []
    },
    source: {
      type: Object,
      default: () => ({})
    }
  },
  methods: {
    resetFields() {
      this.$refs.form.resetFields();
    },
    clearValidate() {
      this.$refs.form.clearValidate();
    },
    async validate() {
      const valid = await this.$refs.form.validate();
      return valid;
    }
  }
};

可以看到,我扩展了一个data字段,用来作为el-select el-checkbox-group el-radio-group的数据源,这些特殊的组件单独列出就行了,基本上也之后有这么几个。

methods里也只是为了方便添加了一些常用的form方法,基本不做逻辑处理。

现在看一下,这样的配置可以生成怎样的表单

注意:我这里定义了一部分全局样式,比如在schema form下的组件,全部占满整格,使其比较美观。

生成这样一个常用的筛选项表单

<template>
  <div>
    <nx-form
      ref="searchForm"
      :source="searchForm"
      :config="searchConfig"
    >
      <div slot="search">
        <el-button type="primary" @click="$refs.nxTable.search(1)">查询</el-button>
        <el-button @click="reset()">重置</el-button>
      </div>
    </nx-form>
  </div>
</template>
<script>
export default {
  data() {
     searchForm: {
        keyWord: '', 
        newsType: '', 
        newsStatus: '', 
        publishTime: [],
        createTime: []
     },
  },
  computed: {
      searchConfig() {
      return [
        {
          key: 'keyWord',
          component: 'el-input',
          span: 8,
          label: '关键字',
          props: {
            placeholder: '标题/创建人',
            clearable: true
          }
        },
        {
          key: 'newsType',
          component: 'el-select',
          span: 8,
          label: '类型:',
          props: {
            placeholder: '请选择',
            clearable: true
          },
          data: this.newsTypes
        },
        {
          key: 'newsStatus',
          component: 'el-select',
          span: 8,
          label: '状态:',
          props: {
            placeholder: '请选择',
            clearable: true
          },
          data: statusTypes
        },
        {
          key: 'publishTime',
          component: 'el-date-picker',
          label: '发布时间:',
          span: 8,
          props: {
            clearable: true,
            valueFormat: 'timestamp',
            type: 'datetimerange',
            defaultTime: ['00:00:00', '23:59:59'],
            rangeSeparator: '-',
            startPlaceholder: '请选择开始时间',
            endPlaceholder: '请选择结束时间'
          }
        },
        {
          key: 'createTime',
          component: 'el-date-picker',
          label: '创建时间:',
          span: 8,
          props: {
            clearable: true,
            valueFormat: 'timestamp',
            type: 'datetimerange',
            defaultTime: ['00:00:00', '23:59:59'],
            rangeSeparator: '-',
            startPlaceholder: '请选择开始时间',
            endPlaceholder: '请选择结束时间'
          }
        },
        {
          component: 'slot',
          slotName: 'search',
          span: 8,
          labelWidth: '0'
        }
      ];
    }
  }
}
</script>

其余的找了一些,也没啥特别的,就不贴了,简单来说,这个百来行的组件,应用在多个大型项目当中,易用性,扩展性,没有出现什么问题,配合我们自定义的其他table组件、dialog组件,十分钟就可以实现一个完整的B端增删改查。

值得一提的是,为了表单的易用性,我们基本上所有的自定义组件都支持了使用v-model做数据绑定,达到简单易用的效果。

结语

代码是找了一个很久的项目写的一个思路,之后的项目中都有改进优化,大致只是分享一个思路,如果有什么想法的,欢迎指正。

 到此这篇关于Vue2 Element Schema Form 配置式生成表单的实现的文章就介绍到这了,更多相关Vue2 Element Schema Form生成表单内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Vue2ElementSchemaForm配置式生成表单的实现

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Vue实现生成二维码的简单方式

与后端生成二维码相比,前端生成二维码更具有灵活性,下面这篇文章主要给大家介绍了关于Vue实现生成二维码的简单方式,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
2023-01-05

python如何实现生成器表达式

小编给大家分享一下python如何实现生成器表达式,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!生成器表达式Python中的生成器是创建迭代器的一种简便方法。因为
2023-06-27

Python中怎么实现列表生成式

Python中怎么实现列表生成式,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1. 方法一是循环:L = [] for x in range(1, 11): L.app
2023-06-15

怎么在python中实现列表生成式

怎么在python中实现列表生成式?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Python主要用来做什么Python主要应用于:1、Web开发;2、数据科学研究;3、网络
2023-06-14

shell生成简单格式的xml实例

以下是shell代码: create_xml.sh#! /bin/bash #author: dengzhaoqun#date: 201202/14 outfile=outtabs=0 put(){echo '<'${*}'>' >> $o
2022-06-04

如何使用PHP实现动态表单生成工具

小编给大家分享一下如何使用PHP实现动态表单生成工具,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!表单包含多种input类型,包括 hiiden类型 ,text类
2023-06-29

Shell脚本实现批量生成nagios配置文件

如果管理的站点和服务器较多的情况下,每次修改配置文件都相当痛苦。因而想到了用shell脚本来批量生成配置文件和配置数据。下面这个脚本是为了批量生成nagios监控配置文件的一个shell脚本程序。其原理是事先定义一个shell脚本模板,然后
2022-06-04

实现core文件自动生成配置文件的方法

本文讲述了实现core文件自动生成的配置方法,具体执行步骤如下: 1.编辑环境配置文件,让shell启动时自动设置ulimitvi /etc/profile ulimit -c unlimited > /dev/null 2>&12.更改c
2022-06-04

如何实现core文件自动生成配置文件

这篇文章主要介绍如何实现core文件自动生成配置文件,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!具体执行步骤如下:1.编辑环境配置文件,让shell启动时自动设置ulimitvi /etc/profileulimi
2023-06-09

Shell脚本怎么实现批量生成nagios配置文件

这篇文章主要讲解了“Shell脚本怎么实现批量生成nagios配置文件”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Shell脚本怎么实现批量生成nagios配置文件”吧!如果管理的站点和服
2023-06-09

Android实现原生侧滑菜单的超简单方式

先来看看效果图当你点击菜单可以更改图标,例如点击happy,首页就会变一个笑脸,这个实现的过程超级简单 你需要使用ToolBar与DrawableLayout两个比较新的控件 首先要写三个xml布局文件,我这里的布局文件是使用了includ
2022-06-06

C++基于单链表如何实现学生成绩管理系统

本文小编为大家详细介绍“C++基于单链表如何实现学生成绩管理系统”,内容详细,步骤清晰,细节处理妥当,希望这篇“C++基于单链表如何实现学生成绩管理系统”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。具体代码如下/
2023-06-30

编程热搜

目录