前言
本文将介绍我们的表单解决方案 @femessage/el-form-renderer, 展示我们在 vue 技术栈下, 我们是如何处理以下问题的:
表单项动态显示或隐藏
表单数据联动
表单输入 / 输出数据格式化
非常规表单项的处理
复杂的表单验证
方案
表单项动态显示或隐藏(hidden)
可以通过 hidden 控制某一表单项的显示或隐藏.
hidden-cn.gif
- <template>
- <el-form-renderer ref="form" :content="content" />
- </template>
- <script>
- export default {
- name: 'hidden',
- data() {
- return {
- content: [
- {
- type: 'select',
- id: 'selected',
- label: '选择项目',
- options: [
- {
- label: '项目 A',
- value: 'optionA'
- },
- {
- label: '项目 B',
- value: 'optionB'
- }
- ]
- },
- {
- label: '资料',
- type: 'input',
- id: 'data',
- el: {
- placeholder: '项目 B 的具体内容'
- },
- hidden: form => form.selected !== 'optionB' // 如果选择项并非 项目 B 则隐藏
- },
- ]
- }
- }
- }
- </script>
表单数据联动(on)
可以通过 on 来监听 blur , focus 等事件来实现表单联动.
举个例子, 填写 fullName 后, 自动填充 lastName
on-cn.gif
- <template>
- <el-form-renderer ref="form" :content="content" />
- </template>
- <script>
- export default {
- data() {
- return {
- content: [
- {
- label: '英文名',
- type: 'input',
- id: 'fullName',
- on: {
- blur: ([event], updateForm) => {
- const value = event.target.value
- const lastName = value.split(' ')[1] // 通过空格分割出内容
- updateForm({ lastName }) // 更新其他表单项
- },
- },
- },
- {
- label: '姓氏',
- type: 'input',
- id: 'lastName',
- }
- ]
- }
- }
- }
- </script>
输入 / 输出格式化(inputFormat/outputFormat)
拿 日期范围选择器 为例, 组件输出的值是一条字符串, 但后端接口格式是两个字段 {startDate, endDate}, 则此时需要对数据进行格式化处理.
inputFormat
转换输入的数据, 使其变成表单项需要的数据格式
- <template>
- <el-form-renderer :content="content" ref="form" />
- </template>
- <script>
- export default {
- data() {
- return {
- content: [
- {
- el: {
- type: 'daterange',
- placeholder: '选择日期',
- valueFormat: 'yyyy-MM-dd'
- },
- type: 'date-picker',
- id: 'date',
- label: '日期',
- // 接口设计的时间范围是两个字段 '2019-07-23','2019-07-24'
- // 处理后的值为 [ '2019-07-23', '2019-07-24' ]
- inputFormat: row => ([row.startDate, row.endDate])
- }
- ]
- }
- }
- }
- </script>
- outputFormat
转换输出的数据, 使其变成需要的 (接口期望的) 数据格式
input3.gif
- <script>
- export default {
- data() {
- return {
- content: [
- {
- el: {
- type: 'daterange',
- placeholder: '选择日期',
- valueFormat: 'yyyy-MM-dd'
- },
- type: 'date-picker',
- id: 'date',
- label: '日期',
- // 处理前的值为 date: [ '2019-07-23', '2019-07-24' ]
- // 处理后的值为 {startDate: '2019-07-23', endDate: '2019-07-24'}
- outputFormat: val => {
- if (!val) {
- return {startDate: '', endDate:''}
- }
- return {
- startDate: val[0],
- endDate: val[1]
- }
- }
- }
- ]
- }
- }
- }
- </script>
自定义组件(component)
@femessage/el-form-renderer 默认支持的 type 有限, 只能渲染常见的表单项. 对于个性化的需求, 比如想渲染一个上传组件, type 就不够用了, 那怎么办呢? 这时候 component 选项就派上用场了.
component 可以渲染自定义组件, 而编写自定义组件的关键是在组件内部实现 v-model:
有一个 props 为 value
对外触发 input 事件
input2.gif
- <!-- 自定义组件 my-input -->
- <template>
- <div class="my-component">
- <el-input :value="value" @input="onInput" />
- <el-button @click="onInput('我帮你输入点东西')">帮我输入点东西</el-button>
- </div>
- </template>
- <script>
- export default {
- props: {
- value: String
- },
- methods: {
- onInput(val) {
- this.$emit('input', val)
- }
- }
- }
- </script>
则可以用 component 属性让 @femessage/el-form-renderer 渲染此自定义组件
- <template>
- <el-form-renderer :content="content"/>
- </template>
- <script>
- import MyInput from '@/components/my-input.vue'
- export default {
- data() {
- return {
- content: [
- {
- component: MyInput,
- id: 'myInput',
- label: '自定义输入框组件'
- }
- ]
- }
- },
- }
- </script>
目前团队对常见的表单扩展组件都根据标准实现了 v-model, 因此都可以不写 template, 由 @femessage/el-form-renderer 实现数据驱动渲染
上传组件 https://github.com/FEMessage/upload-to-ali
富文本编辑器 https://github.com/FEMessage/v-editor
省市区选择器 https://github.com/FEMessage/el-select-area
范围输入框 https://github.com/FEMessage/el-number-range
版本号输入框 https://github.com/FEMessage/el-semver-input
复杂的表单验证(rules)
一个复杂的表单项配置, 往往需要定义一些规则 (rules) 来限制用户输入, 规则里面可能还会有自定义的验证器(validator), 这样的表单项多了之后, 就会导致页面文件的配置项变得很长很长.
解决方案是在组件内部设置校验规则, 从而达到封装隐藏目的. 使用者不用关心表单的验证规则, 直接引入组件并使用就好.
下面展示一个结合自定义组件 (基本输入框) 封装的验证规则, 其规则如下:
不允许空值
只能输入 3 位数或以上
必须以 123 开头
input2.gif
- <template>
- <el-input :value="value" @input="onInput"/>
- </template>
- <script>
- export default {
- rules() {
- return [
- {
- required: true,
- validator: (rule, val, callback) => {
- if (!val) {
- callback(new Error('不能为空!'))
- } else if (!val.length>= 3) {
- callback(new Error('只能输入 3 位数或以上!'))
- } else if (!/^123/.test(val)) {
- callback(new Error('必须是以 123 开头!'))
- } else {
- callback()
- }
- }
- }
- ]
- },
- props: ['value'],
- methods: {
- onInput(val) {
- this.$emit('input', val)
- }
- }
- }
- </script>
结语
我们内部项目都在使用 @femessage/el-form-renderer, 可以在 GitHub 上找到更多信息.
欢迎大家使用, 提高项目开发效率~
来源: http://www.jianshu.com/p/0eb3efb50103