本案例将会讲解如何使用 vue.js + ElementUI 开发一个简单的 可配置组合表单 Demo。
示例源代码 github
操作演示:
在左侧新建表单区块,选择区块标题和表单组件类型后点击确定,会在中间区域生成一个块新的表单,右侧展示了所有表单的数据合并结果。
在本示例中你主要可以看到以下知识点的运用:
- vue.js 单文件组件,
- 组件传参
- 自定义 v-model
- 数据监听
- 数据合并
- 批量自动注册组件
- 使用 mixin 抽取公用代码
- sass 语法
- BEM 规范
- 尽量避免使用 for 循环的写法
<component>
组件- 动态绑定 v-model 到一组数据
上面列举的这些是因为以前有群里朋友询问相关的实现方法,在此列出,可能正在读这篇文章的你已经都掌握了,恭喜你!(本篇文章的起因也是群友提问)
下面开始正文
总览
这个 demo 的所有组件和逻辑如果写在一个文件中大概会有几百行,维护起来会有麻烦,所以首先设计这样的目录结构:
搭建基本框架
为了快速开发页面本项目使用 ElementUI 和 D2Admin 快速搭建,以下示例中组件都来自这两个开源项目,如果你不认识这些组件也没有关系,大致了解意思就可。
首先写出页面的大致框架:
<template>
<d2-container>
<template slot="header">可配置问卷示例</template>
<div class="questionnaire">
<el-container>
<!-- 左侧位置 -->
<!-- 中间位置 -->
<!-- 右侧位置 -->
</el-container>
</div>
<template slot="footer">从左侧选择要添加的表单块,右侧查看结果</template>
</d2-container>
</template>
<script>
export default {
name: 'page1',
components: {
// 这里以后要要注册表单区块 左侧边栏 右侧边栏
},
data () {
return {
formList: [], // 所有注册的表单区块
forms: [] // 用户已经选择的表单区块
}
}
}
</script>
css / sass 暂时先忽略,在最后会展示样式代码
表单区块
新建 page1/components/Form/Form1.vue
作为第一个表单区块
<template>
<el-form ref="form" :model="form" label-position="top">
<el-form-item label="姓名">
<el-input v-model="form.username"></el-input>
</el-form-item>
<el-form-item label="姓名">
<el-radio-group v-model="form.usersex">
<el-radio :label="1">男</el-radio>
<el-radio :label="0">女</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
</template>
<script>
export default {
name: 'Form1',
props: {
value: {
default: () => ({
username: '',
usersex: 1
})
}
},
data () {
return {
form: {
username: '',
usersex: 1
}
}
},
watch: {
form: {
// 处理方法
handler (value) {
this.$emit('input', value)
},
// 深度 watch
deep: true,
// 首先自己执行一次
immediate: true
}
}
}
</script>
这是用 ElementUI 构建的很简单的一个表单,甚至没有校验。
然后我们在页面组件上注册这个表单区块:
<script>
components: {
// 注册组件
Form1: () => import('./components/Form/Form1.vue')
},
data () {
return {
// 注册到数据
formList: [
{
title: '基础',
name: 'Form1'
}
]
}
}
</script>
等等,假如我有 20 个区块,难道要写 20 遍注册,在 formList 里手动加 20 个对象吗?
所以我们先新建了 7 个区块,区块内容都大同小异,并将代码稍加改造:
表单区块示例
<template>
<el-form ref="form" :mo