vue3(五)父子组件通信

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');

posted @ 2024-01-08 14:10  惊朝  阅读(22)  评论(0编辑  收藏  举报