最近搜索

vue3 小案例 复杂编辑的 表格。 投放广告 案例

浏览:14
管理员 2025-07-16 10:44

image.png

目录结构

image.png




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