[Vue3:组件通信)子组件props接收和watch监听,emit发送父组件 (添加修改设置成绩,添加、删除选课记录)

作者 : admin 本文共13380个字,预计阅读时间需要34分钟 发布时间: 2024-06-17 共1人阅读

文章目录

  • 一:系统功能:设置成绩(添加或修改)
    • 交互逻辑:涉及页面 Page02.vue,ModalEdit.vue
    • 主页面Page.vue注入子页面,使用子页面标签属性
    • 主页面对子页面做通信,子页面ModalEdit接收参数和监听时间涉及到组件props,watch
      • 子页面ModalEdit通过props属性接收控制属性
    • 子页面ModalEdit向父页面传递参数
  • 二:系统功能:添加选课
  • 三:系统功能:删除选课
  • 四:相关页面完整代码
    • Page02.vue
    • ModalEdit.vue
    • ModalCourseAdd.vue
  • 五:页面运效果

一:系统功能:设置成绩(添加或修改)

交互逻辑:涉及页面 Page02.vue,ModalEdit.vue

点击成绩修改按钮弹出 成绩修改页面,展示分数并可设置分数
点击提交发送请求/api/baseStudentCourse/updata
成功则返回上一页面进行刷新数据发送请求/api/baseStudentCourse/list

主页面Page.vue注入子页面,使用子页面标签属性

<el-table-column label="操作" width="380">
        <template #default="{ row, $index }">
          <el-button size="mini" type="warning" @click="editItem(row, $index)"  @updateData="handleData"  >成绩修改</el-button>
          <el-button size="mini" type="warning" @click="addItem(row, $index)"  @updateData="handleData"  >成绩添加</el-button>
          <el-button size="mini" type="danger" @click="handleDeleteCourse(row, $index)"  @updateData="handleData"  >删除选课</el-button>
        </template>
      </el-table-column>
    </el-table>
<ModalEdit v-model:visible="showModal" :edit-data="editData" :show-flag = "showFlag" @refreshData="refreshData" />
<ModalCourseAdd v-model:visible="showModalAddCourse" @refreshData="refreshData" />
<script setup>
import { useRouter } from 'vue-router';
import {onMounted, ref} from 'vue';
import axios from "axios";
import ModalEdit from "./ModalEdit.vue";
import ModalCourseAdd from "./ModalCourseAdd.vue";
const showModal = ref(false);
const showModalAddCourse = ref(false);
const editData = ref(null);
const showFlag = ref(String);

主页面对子页面做通信,子页面ModalEdit接收参数和监听时间涉及到组件props,watch

子页面ModalEdit通过props属性接收控制属性

在 Vue.js 中,props 用于接收来自父组件的数据。这里定义了三个属性(props):visible、editData 和 showFlag。我将逐一分析这些属性

父页面Page当点击add或edit, 设置这个showModal.value属性为true(v-model:visible=“showModal”),这里showModal,并给editData赋值
在 Vue 3 中,v-model 可以绑定到组件的任意 prop 上,这里它绑定了 showModal 数据属性,这意味着 showModal 的值将与 ModalEdit 组件内部的 visible 状态保持同步。当 ModalEdit 组件的 visible 状态改变时,它会更新父组件的 showModal 数据属性,反之亦然。
:show-flag=“showFlag”: 类似地,这也是一个动态 prop 绑定,将父组件中的 showFlag 数据传递给 ModalEdit 组件。showFlag 可能用于控制模态框中某些元素的显示或隐藏。

const editItem = (item, index) => {
  editData.value = item;
  showModal.value = true; //  v-model:visible="showModal"
  showFlag.value = '成绩修改';
};
const addItem = (item, index) => {
  editData.value = item;
  showModal.value = true;
  showFlag.value = '成绩添加';
};

watch是vue组件的一个选项,这里是用来监视visible这个数据属性的变化;
父页面visible属性默认是false

<ModalEdit v-model:visible="showModal" :edit-data="editData" :show-flag = "showFlag" @refreshData="refreshData" />
const showModal = ref(false);

父页面点击操作visible设置true,子页面同时watch监听visible发生变化,editData展示和渲染默认成绩数据,visible 为true展示页面(默认隐藏)

watch: {
    visible() {
      this.formData.id = this.editData.id; // 初始化id字段
      this.formData.score = this.editData.score;
      // this.formData.score = this.editData.score;
    }
  },
  props: {
    visible: {
      type: Boolean,
      required: true
    },
    editData: {
      type: Object,
      default: () => ({})
    },
    showFlag: {
      type: Object,
      default: () => ({})
    }
  },

子页面ModalEdit向父页面传递参数

这部分定义了该组件可能向父组件发出的三个自定义事件:
update:visible:通常用于更新一个名为 visible 的 prop 的值,这是 Vue 的 .sync 修饰符常用的模式。
submit:可能是当表单数据被提交时触发的事件。
refreshData:可能是当数据更新后,通知父组件刷新或重新获取数据的事件。

这里主要用了refreshData事件:当子页面更新成功后通知父组件事件函数(重新请求刷新数据)
ModalEdit
子页面:

this.$emit('refreshData', { // 假设服务器返回了更新后的数据,或者你可以传递更新后的id和score
            success: true,
            message: resp.data.message,
 });

父页面:

<template>
		<ModalEdit v-model:visible="showModal" :edit-data="editData" :show-flag = "showFlag" @refreshData="refreshData" />
</template>
<script setup>
// 成绩修改
const refreshData = () => {
  axios.post("/api/baseStudentCourse/list", {
    id: localStorage.getItem('id')}).then(resp => {
    if (resp.data.code === 200) {
      tableData.value = resp.data.data
    } else {
      alert(resp.data.message);
    }
  })
  showModal.value = false;
  showModalAddCourse.value = false;
} ;
</script>
  emits: ['update:visible', 'submit', 'refreshData'],
  methods: {
    handleSubmit() {
      // 确保发送完整对象,包含id字段
      this.$emit('submit', { ...this.formData });
    },
    closeModal() {
      this.$emit('update:visible', false);
    },
    // 成绩录入/修改
    submit () {
      debugger
      console.log(this.formData)
      // 编辑逻辑
      const response = axios.post("/api/baseStudentCourse/update", {
        id: this.formData.id,
        score: this.formData.score
      }).then(resp => {
        if (resp.data.code === 200) {
          alert(resp.data.message);
          // 发送一个事件给父组件,表示数据已更新
          this.$emit('refreshData', { // 假设服务器返回了更新后的数据,或者你可以传递更新后的id和score
            success: true,
            message: resp.data.message,
          });
        } else {
          alert(resp.data.message);
        }
      })
    }
  }

二:系统功能:添加选课

父组件与子组件交互和上述设置成绩交互逻辑一致,
主要是多了进入子页面展示下拉列表:v-for,

<form @submit.prevent="handleSubmit">
<label>
选择学生:
<select v-model="formData.student">
<option v-for="student in students" :key="student.id" :value="student.id">
{{ student.name }}
</option>
</select>
</label>
<label>
选择课程:
<select v-model="formData.course">
<option v-for="course in courses" :key="course.id" :value="course.id">
{{ course.name }}
</option>
</select>
</label>
<!-- 其他需要编辑的字段也可以在这里添加 -->
<button type="submit" @click="submit">提交</button>
<button @click="closeModal">取消</button>
</form>
<script>
import axios from "axios";
export default {
props: {
visible: {
type: Boolean,
required: true
},
showFlag: {
type: Object,
default: () => ({})
}
},
emits: ['update:visible', 'submit', 'refreshData'],
data() {
return {
formData: {
id: null, // 添加id字段
score: null
}
};
},
created () {
axios.post("/api/student/list", {}).then(res => {
if (res.data.code === 200) {
debugger
this.students = res.data.data
}
})
axios.post("/api/course/list", {}).then(resp => {
if (resp.data.code === 200) {
debugger
this.courses = resp.data.data
}
})
console.log("准备输出课程和学生信息")
console.log(this.courses)
console.log(this.students)
},
methods: {
closeModal() {
this.$emit('update:visible', false);
},
// 成绩录入/修改
submit() {
console.log(this.formData)
// 编辑逻辑
axios.post("/api/baseStudentCourse/save", {
studentId: this.formData.student,
courseId: this.formData.course,
teacherId: localStorage.getItem('id')
}).then(resp => {

三:系统功能:删除选课

直接删除当前行数据
// 删除选课

const handleDeleteCourse = (row, index) => {
console.log(row)
axios.post("/api/baseStudentCourse/delete", {
id: row.id
}).then(resp => {
if (resp.data.code === 200) {
alert(resp.data.message);
axios.post("/api/baseStudentCourse/list", {
id: localStorage.getItem('id')}).then(resp => {
if (resp.data.code === 200) {
tableData.value = resp.data.data
} else {
alert(resp.data.message);
}
})
} else {
alert(resp.data.message);
}
})
};

四:相关页面完整代码

Page02.vue

<template>
<div class="container">
<div class="title-container" style="margin-top: 20px;">
<h3 class="title">学生管理平台</h3>
</div>
<div class="user-info">
<div class="buttons">
<el-button size="mini" class="user-button primary" @click="handleAddCourse()" :closeCourseModal = "closeModal">添加选课</el-button>
&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;
&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;
&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;
&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;
<span><b>当前用户:</b></span>{{currentUser}}
<el-button size="mini" class="user-button" @click="resetUser()">注销当前用户</el-button>
</div>
<!--      
当前登录用户:{{ localStorageValue }}
-->
</div> <el-table :data="tableData"> <el-table-column prop="id" label="编码" width="100"></el-table-column> <el-table-column prop="studentId" label="学号" width="100"></el-table-column> <el-table-column prop="studentName" label="学生" width="100"></el-table-column> <el-table-column prop="courseName" label="课程" width="180"></el-table-column> <el-table-column prop="majorName" label="专业" width="100"></el-table-column> <el-table-column prop="score" label="分数" width="100"></el-table-column> <el-table-column prop="teacherName" label="教师" width="100"></el-table-column> <el-table-column label="操作" width="380"> <template #default="{ row, $index }"> <el-button size="mini" type="warning" @click="editItem(row, $index)" @updateData="handleData" >成绩修改</el-button> <el-button size="mini" type="warning" @click="addItem(row, $index)" @updateData="handleData" >成绩添加</el-button> <el-button size="mini" type="danger" @click="handleDeleteCourse(row, $index)" @updateData="handleData" >删除选课</el-button> </template> </el-table-column> </el-table> <ModalEdit v-model:visible="showModal" :edit-data="editData" :show-flag = "showFlag" @refreshData="refreshData" /> <ModalCourseAdd v-model:visible="showModalAddCourse" @refreshData="refreshData" /> </div> </template> <script setup> import { useRouter } from 'vue-router'; import {onMounted, ref} from 'vue'; import axios from "axios"; import ModalEdit from "./ModalEdit.vue"; import ModalCourseAdd from "./ModalCourseAdd.vue"; const tableData = ref([]); // 使用ref来创建响应式数据 onMounted(async () => { const response = await axios.post("/api/baseStudentCourse/list", { id: localStorage.getItem('id')}); tableData.value = response.data.data; // 将请求结果赋值给响应式数据 }); const currentUser = localStorage.getItem("username"); const showModal = ref(false); const showModalAddCourse = ref(false); const editData = ref(null); const showFlag = ref(String); const editItem = (item, index) => { editData.value = item; showModal.value = true; showFlag.value = '成绩修改'; }; const addItem = (item, index) => { editData.value = item; showModal.value = true; showFlag.value = '成绩添加'; }; const closeModal = () => { showModalAddCourse.value = false }; const handleData = () => { console.log("Page02 handleData") const response = axios.post("/api/baseStudentCourse/list", { id: localStorage.getItem('id')}); tableData.value = response.data.data; // 将请求结果赋值给响应式数据; console.log(response) }; const router = useRouter(); const resetUser = () => { // 编辑逻辑 const key = 'id'; // 替换为你需要获取的localStorage的key const value = localStorage.getItem(key); // 如果需要解析JSON,可以在这里进行解析 try { axios.post("/api/base/reset", { id: localStorage.getItem('id') }).then(resp => { if (resp.data.code === 200) { alert(resp.data.message); localStorage.removeItem(localStorage.getItem('id')) router.push('/') } else { alert(resp.data.message); } }) } catch (error) { console.error(error); // 处理错误 } }; // 添加选课 const handleAddCourse = () => { debugger // editData.value = item; showModalAddCourse.value = true; }; // 删除选课 const handleDeleteCourse = (row, index) => { console.log(row) axios.post("/api/baseStudentCourse/delete", { id: row.id }).then(resp => { if (resp.data.code === 200) { alert(resp.data.message); axios.post("/api/baseStudentCourse/list", { id: localStorage.getItem('id')}).then(resp => { if (resp.data.code === 200) { tableData.value = resp.data.data } else { alert(resp.data.message); } }) } else { alert(resp.data.message); } }) }; const updateList = (updatedItem) => { // 假设使用index来更新list,但这种方式不推荐,如果数据顺序改变会有问题 const index = tableData.value.findIndex(item => item.id === updatedItem.id); tableData.value.splice(index, 1, updatedItem); showModal.value = false; }; // 成绩修改 const refreshData = () => { axios.post("/api/baseStudentCourse/list", { id: localStorage.getItem('id')}).then(resp => { if (resp.data.code === 200) { tableData.value = resp.data.data } else { alert(resp.data.message); } }) showModal.value = false; showModalAddCourse.value = false; } ; // console.log(""") </script>

ModalEdit.vue

<template>
<div v-if="visible" class="modal">
<div class="modal-content">
<!--      

编辑数据

-->
<h2>{{ showFlag }}</h2> <form @submit.prevent="handleSubmit"> <label> 分数: <input type="text" v-model="formData.score" /> </label> <!-- 其他需要编辑的字段也可以在这里添加 --> <button type="submit" @click="submit()">提交</button> <button @click="closeModal">取消</button> </form> </div> </div> </template> <script> import axios from "axios"; export default { watch: { visible() { this.formData.id = this.editData.id; // 初始化id字段 this.formData.score = this.editData.score; // this.formData.score = this.editData.score; } }, props: { visible: { type: Boolean, required: true }, editData: { type: Object, default: () => ({}) }, showFlag: { type: Object, default: () => ({}) } }, emits: ['update:visible', 'submit', 'refreshData'], data() { return { formData: { id: null, // 添加id字段 score: null } }; }, methods: { handleSubmit() { // 确保发送完整对象,包含id字段 this.$emit('submit', { ...this.formData }); }, closeModal() { this.$emit('update:visible', false); }, // 成绩录入/修改 submit () { debugger console.log(this.formData) // 编辑逻辑 const response = axios.post("/api/baseStudentCourse/update", { id: this.formData.id, score: this.formData.score }).then(resp => { if (resp.data.code === 200) { alert(resp.data.message); // 发送一个事件给父组件,表示数据已更新 this.$emit('refreshData', { // 假设服务器返回了更新后的数据,或者你可以传递更新后的id和score success: true, message: resp.data.message, }); } else { alert(resp.data.message); } }) } } }; </script> <style scoped> .modal { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); display: flex; justify-content: center; align-items: center; z-index: 1000; } .modal-content { background-color: #fff; padding: 20px; border-radius: 5px; } </style>

ModalCourseAdd.vue

<template>
<div v-if="visible" class="modal">
<div class="modal-content">
<h2>添加选课</h2>
<form @submit.prevent="handleSubmit">
<label>
选择学生:
<select v-model="formData.student">
<option v-for="student in students" :key="student.id" :value="student.id">
{{ student.name }}
</option>
</select>
</label>
<label>
选择课程:
<select v-model="formData.course">
<option v-for="course in courses" :key="course.id" :value="course.id">
{{ course.name }}
</option>
</select>
</label>
<!-- 其他需要编辑的字段也可以在这里添加 -->
<button type="submit" @click="submit">提交</button>
<button @click="closeModal">取消</button>
</form>
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
props: {
visible: {
type: Boolean,
required: true
},
showFlag: {
type: Object,
default: () => ({})
}
},
emits: ['update:visible', 'submit', 'refreshData'],
data() {
return {
formData: {
id: null, // 添加id字段
score: null
}
};
},
created () {
axios.post("/api/student/list", {}).then(res => {
if (res.data.code === 200) {
debugger
this.students = res.data.data
}
})
axios.post("/api/course/list", {}).then(resp => {
if (resp.data.code === 200) {
debugger
this.courses = resp.data.data
}
})
console.log("准备输出课程和学生信息")
console.log(this.courses)
console.log(this.students)
},
methods: {
closeModal() {
this.$emit('update:visible', false);
},
// 成绩录入/修改
submit() {
console.log(this.formData)
// 编辑逻辑
axios.post("/api/baseStudentCourse/save", {
studentId: this.formData.student,
courseId: this.formData.course,
teacherId: localStorage.getItem('id')
}).then(resp => {
if (resp.data.code === 200) {
alert(resp.data.message);
// 发送一个事件给父组件,表示数据已更新
this.$emit('refreshData', { // 假设服务器返回了更新后的数据,或者你可以传递更新后的id和score
success: true,
message: resp.data.message,
});
} else {
alert(resp.data.message);
}
})
}
}
};
</script>
<style scoped>
.modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-content {
background-color: #fff;
padding: 20px;
border-radius: 5px;
}
</style>

五:页面运效果

[Vue3:组件通信)子组件props接收和watch监听,emit发送父组件 (添加修改设置成绩,添加、删除选课记录)插图

[Vue3:组件通信)子组件props接收和watch监听,emit发送父组件 (添加修改设置成绩,添加、删除选课记录)插图(1)

[Vue3:组件通信)子组件props接收和watch监听,emit发送父组件 (添加修改设置成绩,添加、删除选课记录)插图(2)
[Vue3:组件通信)子组件props接收和watch监听,emit发送父组件 (添加修改设置成绩,添加、删除选课记录)插图(3)
[Vue3:组件通信)子组件props接收和watch监听,emit发送父组件 (添加修改设置成绩,添加、删除选课记录)插图(4)

本站无任何商业行为
个人在线分享 » [Vue3:组件通信)子组件props接收和watch监听,emit发送父组件 (添加修改设置成绩,添加、删除选课记录)
E-->