export interface Student{
id: string,
name: string,
grade: number,
score: number,
}
// src/views/Father.vue
<template>
<!-- emitEvent-Child是kebab命名,官方推荐这种命名方法,因为事件监听器在DOM模板中会被自动转成全小写,html对大小写不敏感 -->
<Child ref="ChildRef" @close-alert="CloseAlert" v-model="ifShowAlert" :studentsToChild = "studentToChild"/>
<!-- ChildRef是Child组件的实例 -->
<div class="common-layout">
<el-container>
<el-header class="NavBar">学生数据一览</el-header>
<el-card class="main">
<div class="studentData" v-for="i in studentList" :key="i.id" >
<span class="spanFirst">学号:{{ i.id }}</span>
<span class="spanOrdinary">姓名:{{ i.name }}</span>
<span class="spanOrdinary">班级:{{ i.grade }} 班</span>
<span class="spanOrdinary">分数:{{ i.score }}</span>
<span class="spanOrdinary">
<button @click="OpenAlert(i,studentList.indexOf(i))">修改</button>
</span>
</div>
</el-card>
</el-container>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import Child from './Child.vue'
import { useStudentsStore } from '@/store/students';
import type { Student } from "@/interface/Student";
const studentsStore = useStudentsStore();
let studentList = studentsStore.studentList;
let studentToChild:Student = reactive<Student>({id: '',name: '',grade: 0,score: 0,});
const ChildRef = ref();
let ifShowAlert = ref(false);
function CloseAlert(){
ifShowAlert.value = false;
console.log(studentList);
}
function OpenAlert(i:Student,n:number){
ifShowAlert.value = true;
studentToChild = i;
ChildRef.value.studentIndex = n;
}
</script>
<style scoped>
.NavBar{
text-align: center;
background-color: #d9ecff;
height: 40px;
border: 1px solid var(--el-border-color);
border-radius: 20px;
margin-top: 20px;
margin-left: 100px;
margin-right: 100px;
padding-top: 10px;
padding-bottom: 32px;
}
.main{
background-color: #ecf5ff;
border-radius: 15px;
margin-top: 20px;
margin-left: 100px;
margin-right: 100px;
}
.studentData{
text-align: center;
margin-top: 10px;
}
.spanOrdinary{
margin-left: 80px;
}
</style>
// src/views/Child.vue
<template>
<el-dialog v-model="dialogFormVisible" title="信息修改">
<el-form>
<el-form-item label="学号">
<div>{{ studentsToChild.id }}</div>
</el-form-item>
<el-form-item label="姓名">
<div>{{ studentsToChild.name }}</div>
</el-form-item>
<el-form-item label="班级">
<el-input v-model="studentsToChild.grade"/>
</el-form-item>
<el-form-item label="分数">
<el-input v-model="studentsToChild.score"/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="closeAlert">Cancel</el-button>
<el-button type="primary" @click="SubmitAlert">Confirm</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, toRef } from 'vue'
import type { Student } from "@/interface/Student";
const dialogFormVisible = ref(true);
const emit = defineEmits(['close-alert']);//子组件通过close-alert触发父组件的事件CloseAlert,并将子组件的数据作为参数通过事件CloseAlert传递给父组件
const studentIndex = ref();
const myprops = defineProps(['studentsToChild']); // 这里拿到的数据,所以上面的html代码才可以使用
let msgRecieve:Student = toRef(myprops.studentsToChild);
function closeAlert(){
emit('close-alert',false); // 子组件触发父组件的自定义事件(子组件传给父组件的参数是false)
}
function SubmitAlert(){
emit('close-alert',false);
}
defineExpose({studentIndex});
//<script setup> 的组件是默认私有的:一个父组件无法访问到一个使用了<script setup>的子组件中的任何东西,除非子组件在其中通过defineExpose宏显式暴露
</script>
<style scoped>
.dialog-footer button:first-child {
margin-right: 10px;
}
</style>
// App.vue
<template>
<Father />
</template>
<script lang="ts" setup>
import Father from './views/Father.vue';
</script>
<style>
</style>
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import { createPinia } from 'pinia'
const app = createApp(App);
const pinia = createPinia();
app.use(ElementPlus);
app.use(pinia);
app.mount('#app');