
目录结构

index
<template>
<div style="padding: 15px;">
<h2> vue复杂联动表单需求</h2>
{{formData}}
<h2>投放区域</h2>
<el-select v-model="selectArr" @change="selectChange" multiple>
<el-option v-for="option in optionArr" :value="option.value" :label="option.label" :key="index"></el-option>
</el-select>
<!-- <el-select filterable v-model="form.level" placeholder="请选择项目级别" >-->
<!-- <template v-for="item in Object.keys(levelMap)" :key="item">-->
<!-- <el-option :label="levelMap[item]" :value="parseInt(item)"></el-option>-->
<!-- </template>-->
<!-- </el-select>-->
<DetailTable :formData="formData" :optionMap="optionMap" />
<CrowEdit ref="crowRef" />
<div>
<el-button type="primary" @click="sub">提交</el-button>
</div>
</div>
</template>
<script setup>
import requestUtil from "@/util/request";
import store from '@/store'
import {ref, computed , onMounted,nextTick , reactive,onBeforeMount, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted} from 'vue'
import {ElMessage} from 'element-plus'
import router from '@/router'
import Cookies from "js-cookie";
import { encrypt, decrypt } from "@/util/jsencrypt";
import {Check, Delete, Edit, Message, Search, Star,} from '@element-plus/icons-vue'
import DetailTable from "./detaiTable"
import CrowEdit from "./crowEdit"
const optionArr = [
{
value:"app-head",
label:"app头部"
},
{
value:"app-banner",
label:"首页banner"
},
{
value:"msg",
label:"消息推送"
},
]
//转成对象 后面好取用。 可以直接使用 optionMap[app-banner] 取到对应的文字。如果不用这种, arr就要使用下标,我们又不知道 下标是多少。
const optionMap = {}
optionArr.forEach((item)=>{
optionMap[item.value] = item.label
});
console.log(optionMap);
const crowRef = ref(null);
const formData = ref([]);//这里面放的数据是
// {
// name : valueCode,
// details:{
// duty:""
// },
// crowd:[]
// }
//当我们选择一个选项 之后,formData就会添加一个对象。
const selectChange = (value)=>{
// value是个数组:["app-head", "app-banner"]
const arr_ = value.map((valueCode)=>{
let isExit = false;//默认当前不存在。
formData.value.forEach((item)=>{
if(item.name==valueCode){
//如果相等 就代表当前这个值存在于formData 无需新建 直接使用当前
isExit = item;
}
})
if(isExit){
return isExit;//返回之前的item 复用。
}else{
return {
name : valueCode,
details:{
duty:""
},
crowd:[]
}
}
})
formData.value = arr_;
}
//这个代码 删除也不会报错,因为默认就是显示 我们选择的东西。
const selectArr = computed(() => {
//这个地方是让select显示 选择的东西。
return formData.value.map((item)=>{
return item.name;
})
});
const sub = ()=>{
console.log(crowRef.value.crowArr);
console.log(crowRef.value.crowArr[0]);
console.log(crowRef.value.crowArr[0].crowName);
const crowArr = crowRef.value.crowArr;
formData.value.forEach((item)=>{
item.crowd = crowArr;
});
console.log(formData.value);
}
onMounted(()=>{
//设置回显示功能。
// setTimeout(()=>{
// const res = [ { "name": "app-head", "details": { "duty": "11" }, "crowd": [ { "crowName": "111", "crowSize": "333" }, { "crowName": "222", "crowSize": "33" } ] }, { "name": "msg", "details": { "duty": "222" }, "crowd": [ { "crowName": "111", "crowSize": "333" }, { "crowName": "222", "crowSize": "33" } ] } ];
// formData.value = res;
// //res[0].crowd 是数组。 就是全部的数据。5行或者10行。 因为0 1 2 3 他们都是重复,使用哪一个都行。
// crowRef.value.setCrow(res[0].crowd);
// },800)
})
</script>
<style scoped>
h2{
font-size: 30px;
padding: 10px 0px;
font-weight: bold;
}
</style>detailTalbe
<template>
<div>
<h2>投放详细</h2>
<el-table :data="formData">
<el-table-column label="区域名称" prop="name">
<template #default="scope">
{{optionMap[scope.row.name]}}
</template>
</el-table-column>
<el-table-column label="投放负责人">
<template #default="scope">
<el-input v-model="scope.row.details.duty" />
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup>
const {formData ,optionMap } = defineProps(['formData','optionMap'])
// const props=defineProps(
// {
// id:{
// type:Number,
// default:-1,
// required:true
// },
// dialogTitle:{
// type:String,
// default:'',
// required:true
// },
// //这是是否显示 。窗口
// dialogVisible:{
// type:Boolean,
// default:false,
// required:true
// }
// }
// )
</script>
<style scoped>
h2{
font-size: 30px;
padding: 10px 0px;
font-weight: bold;
}
</style>crowEdit
<template>
<div>
{{crowArr}}
<h2>目标人群</h2>
<el-table :data="crowArr">
<el-table-column label="人群名称" prop="name">
<template #default="scope">
<el-input v-model="scope.row.crowName" />
</template>
</el-table-column>
<el-table-column label="目标量记">
<template #default="scope">
<el-input v-model="scope.row.crowSize" />
</template>
</el-table-column>
</el-table>
<el-button @click="add">添加目标人群</el-button>
</div>
</template>
<script setup>
import {ref, computed , onMounted,nextTick , reactive,onBeforeMount, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted} from 'vue'
const crowArr = ref([]);
const setCrow = (crowd) =>{
crowArr.value = crowd;
}
defineExpose({
crowArr ,setCrow
});// 将方法 或者 数据 爆露给父组件。
//console.log(crowRef.value.crowArr); 这样调用我们需要的数据。
const add=()=>{
crowArr.value.push ({
crowName:"",
crowSize:"",
});
}
</script>
<style scoped>
h2{
font-size: 30px;
padding: 10px 0px;
font-weight: bold;
}
</style><DetailTable :formData="formData" :optionMap="optionMap" />
formData 这个组件内部修改 父组件 也是 实时显示的。
我们之前用了。emits('update:modelValue',false)
为什么之前要这样用。 不是实时通讯的吗。 是不是dialog有关?
这个需要验证一下。
const optionArr = [
{
value:"app-head",
label:"app头部"
},
{
value:"app-banner",
label:"首页banner"
},
{
value:"msg",
label:"消息推送"
},
]
//转成对象 后面好取用。 可以直接使用 optionMap[app-banner] 取到对应的文字。如果不用这种, arr就要使用下标,我们又不知道 下标是多少。
const optionMap = {}
optionArr.forEach((item)=>{
optionMap[item.value] = item.label
});
数组转对象这个技巧我之前 不会。 这个需要学习一下。站长微信:xiaomao0055
站长QQ:14496453