今天写了个动态表单,给大家看一看
当我们输入内容的时候根据,输入的内容判断下面展示什么表单
上代码
<template>
<div class="dynamicFrom">
<pre>
{{ from }}
</pre
>
<div>
<div v-for="(item, index) in formshow" :key="index" class="formItem">
{{ item.name }}
<component
v-on="item.events"
:model-value="item.value"
:is="item.type"
></component>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { defineOptions } from "vue"
import { ElInput } from "element-plus"
defineOptions({
name: "propsTable",
components: {
ElInput,
},
})
const from = ref({
name: {
value: "",
name: "名字",
type: "ElInput",
visibe: true,
next(e) {
if (e == "张三") {
return {
name: "age",
visibe: true,
}
} else {
return {
name: "age",
visibe: false,
}
}
},
},
age: {
value: 18,
name: "年龄",
visibe: false,
type: "ElInput",
next(e) {
if (e == "1") {
return {
name: "nali",
visibe: true,
}
} else {
return {
name: "nali",
visibe: false,
}
}
},
},
nex: {
value: "张三",
type: "ElInput",
visibe: false,
name: "南门",
},
nali: {
value: "张三",
visibe: false,
type: "ElInput",
name: "哪里",
},
})
const formshow = computed(() => {
const res = Object.keys(from.value).map((item) => {
if (from.value[item].visibe) {
return {
...from.value[item],
events: {
input: (e: any) => {
UpdateComponent(item, e)
},
},
}
}
})
let filteredArr = res.filter((item) => item)
return filteredArr
})
const UpdateComponent = (key, value) => {
let bloke
if (from.value[key].next) {
bloke = from.value[key].next(value)
from.value[bloke.name].visibe = bloke.visibe
}
if (from.value[key]?.visibe && bloke?.visibe == false) {
Lun(from.value[key].next(value), value)
}
from.value[key].value = value
}
const Lun = (e, value) => {
from.value[e.name].value = ""
from.value[e.name].visibe = false
if (from.value[e.name].next) {
Lun(from.value[e.name].next(value), value)
}
}
</script>
<style lang="scss" scoped>
.dynamicFrom {
// height: 300px;
width: 300px;
display: flex;
}
</style>
这里通过一个原有对象,负责展示数据,还有个计算属性展示第一次要展示的内容。
/**
* value: 绑定值
* name: 表单名称
* type: 组件类型
* visibe: 是否显示
* next: 下一个组件
*/
const from = ref({
name: {
value: "",
name: "名字",
type: "ElInput",
visibe: true,
next(e) {
if (e == "张三") {
return {
name: "age",
visibe: true,
}
} else {
return {
name: "age",
visibe: false,
}
}
},
},
age: {
value: 18,
name: "年龄",
visibe: false,
type: "ElInput",
next(e) {
if (e == "1") {
return {
name: "nali",
visibe: true,
}
} else {
return {
name: "nali",
visibe: false,
}
}
},
},
nex: {
value: "张三",
type: "ElInput",
visibe: false,
name: "南门",
},
nali: {
value: "张三",
visibe: false,
type: "ElInput",
name: "哪里",
},
})
/**
* 因为有的表单是第一次展示
* 所以需要过滤,
* 这里面有个 events 是负责直接穿透 component 的事件,绑定他的修改值
*/
const formshow = computed(() => {
const res = Object.keys(from.value).map((item) => {
if (from.value[item].visibe) {
return {
...from.value[item],
events: {
input: (e: any) => {
UpdateComponent(item, e)
},
},
}
}
})
let filteredArr = res.filter((item) => item)
return filteredArr
})
/**
* 更新表单
* @param key 表单key
* @param value 表单值
*/
const UpdateComponent = (key, value) => {
let bloke
if (from.value[key].next) {
bloke = from.value[key].next(value)
from.value[bloke.name].visibe = bloke.visibe
}
if (from.value[key]?.visibe && bloke?.visibe == false) {
Lun(from.value[key].next(value), value)
}
from.value[key].value = value
}
/**
* 这里是,当一个值修改了,他的后续因为他要展示的表单都关闭,
* 所有用递归组件,把有 next 的表单都滞空
*/
const Lun = (e, value) => {
from.value[e.name].value = ""
from.value[e.name].visibe = false
if (from.value[e.name].next) {
Lun(from.value[e.name].next(value), value)
}
}