1、组件通讯
每个组件有自己的数据, 提供在data中;每个组件数据独立, 组件数据无法互相直接访问 (合理的)
但是如果需要跨组件访问数据, 怎么办呢? => 组件通信组件通信的方式有很多: 现在先关注两种, 父传子 子传父。
2、组件通信 - 父传子
首先明确父和子是谁, 在父引入子 (被引入的是子)
父传子语法:
1. 父组件通过给子组件加属性传值
2. 子组件中, 通过props属性接收
(1)在父组件中通过给子组件加属性传值
<template>
<div>
<div class="row">
<div class="col-12 pt-3">
<!-- 2、父组件通过给子组件加属性list传值,语法为冒号 :属性名="属性值。属性值的变量需在data中声明" -->
<subject-table :list="list" @remove="delSubject"></subject-table>
</div>
</div>
</div>
</template>
<script>
import SubjectTable from './components/subject-table.vue'
export default {
data () {
return {
//1、声明变量list,即要传递给子组件的属性名的属性值
list: [
{
id: 100,
subject: "语文",
score: 99,
time: new Date("2010-08-12"),
},
{
id: 101,
subject: "数学",
score: 34,
time: new Date("2020-09-01"),
},
{
id: 102,
subject: "英语",
score: 25,
time: new Date("2018-11-22"),
},
{
id: 103,
subject: "体育",
score: 99,
time: new Date("2010-08-12"),
},
],
}
},
}
</script>
<style scoped></style>
(2)子组件中, 通过props属性接收
<script>
import moment from "moment"
export default {
//子组件通过props属性接收
//props: ['list'],
//或者属性值也可以写成对象,接收数据的同时还可以校验数据类型
props: {
list: Object
},
data () {
return {
}
},
methods: {
}
</script>
3、组件通信 - 子传父
在vue中需要遵循单向数据流原则:(从父到子的单向数据流动, 叫单向数据流)。
1. 父组件的数据变化了,会自动向下流动影响到子组件。
2. 子组件不能直接修改父组件传递过来的 props, props是只读的。
vue不提倡子组件直接修改父组件的数据,因为子组件太多会难以追溯是哪个组件修改了父组件数据,导致代码难以维护。vue提倡子组件通过发射事件给父组件,让父组件亲自修改父组件的数据,也就是子传父。
子传父的基本语法:
1. 子组件可以通过 `this.$emit('事件名', 参数1, 参数2, ...)` 触发事件的同时传参给父组件。
2. 父组件监听子组件发送的事件;且父组件要提供对应的函数接收参数,执行业务代码。
(1)子组件发射事件给父组件
<template>
<div class="">
<table class="table table-bordered">
<thead>
<tr>
<th scope="col">编号</th>
<th scope="col">科目</th>
<th scope="col">成绩</th>
<th scope="col">考试时间</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in list" :key="item.id">
<th scope="row">{{index}}</th>
<td>{{item.subject}}</td>
<td>{{item.score}}</td>
<td>{{timeFormat(item.time)}}</td>
<td>
<button type="button" class="btn btn-link"
<!-- 子组件通过触发事件将参数index传给父组件 -->
@click="$emit('remove',index)">删除</button>
</td>
</tr>
<tr class="bg-light">
<th scope="row">统计</th>
<td colspan="2">总分:{{total}}</td>
<td colspan="2">平均分:{{avg}}</td>
</tr>
</tbody>
<tfoot style="display: none">
<tr>
<td class="text-center" colspan="5">暂无数据</td>
</tr>
</tfoot>
</table>
</div>
</template>
<script>
export default {
props: ['list'],
data () {
return {
}
},
methods: {
remove(){
this.$emit('remove',
})
}
}
}
</script>
<style scoped></style>
tip: 子组件发射事件还有另一种写法
子组件标签中写@触发事件名="函数名";同时在子组件的method方法中定义要执行的函数:如下例子的写法
// 1、子组件标签中写@触发事件名="函数名"
<form class="row align-items-center" @submit.prevent="add">
<div class="col-3">
<input type="text" class="form-control" placeholder="请输入科目" v-model.trim="subject" />
</div>
<div class="col-3">
<input type="text" class="form-control" placeholder="请输入分数" v-model.number="score"/>
</div>
<div class="col-3">
<button type="submit" class="btn btn-primary">添加</button>
</div>
</form>
export default {
props: ['list'],
data () {
return {
subject: '',
score: ''
}
},
methods: {
//2、在子组件的method方法中定义要执行的函数
add(){
this.$emit('add',{
subject:this.subject,
score: this.score
})
}
}
}
(2)父组件监听子组件发送的事件,提供对应的函数接收参数,执行业务代码
//父组件监听事件,语法为@事件名=父组件methods函数,delSubject为在methods中定义的函数
<subject-table :list="list" @remove="delSubject"></subject-table>
//delSubject为父组件在methods中定义的函数
methods{
delSubject(index){
this.list.splice(index,1)
},}