组件间的通信方式(三种)

1.props

  • 首先适用于父传子
  • 父组件向子组件传递数据时,要在父组件中引入子组件,在子组件引入的地方绑定一个属性,属性值 就是父组件向子组件传递的数据

  • 这个自定义属性的属性值就是存放父组件向子组件传递的数据

  • 从父组件传递过来的数据没有限制,可以是字符串,表达式,对象等

//父组件
<template>
    <div>
        <Student :students="studentList"/>
    </div>
</template>

<script>
    // 引入School组件
    import Student from './components/Student'
    export default {
        name:'App',
        components:{Student},
        data(){
            return{
                studentList: ['卿卿', '四喜', '快快']
            }
        },  
    }
</script>
<template>
    <div>
        <span v-for="(item, index) in students" :key="index">{
   
   {item}}</span>
    </div>
</template>

<script>
export default{
    name:'Student',
    props: ['students']
}
</script>
  •  也适用于子传父(首先要求父组件给子组件传一个函数用来接收回调)
//父组件
<template>
    <div>
    	<!--通过父组件传给子组件传递函数类型的props实现:子给父传递数据-->
    	//<Student  : 子组件发送数据时调用的方法名=" 父组件接收数据的方法名 "></Student>
        <Student :getStudentName="getStudentName"/>
    </div>
</template>

<script>
    // 引入School组件
    import Student from './components/Student'
    export default {
        name:'App',
        components:{Student},
        methods:{
            getStudentName(name){
                //从子组件接收到传递过来的参数
                console.log('School接收到了学生名',name)
            }
        }
    }
</script>
//子组件
<template>
    <div>
        <button @click="sendStudentName">把学生名给School</button>
    </div>
</template>

<script>
export default{
    name:'Student',
    data(){
        return{
            name:'卿卿'
        }
    },
    props: ['getStudentName'],
    methods:{
       	//发送学生名给父组件
        sendStudentName(){
            //调用从父组件中props过来的getSchoolName方法,将学校名称通过参数形式传过去
            this.getStudentName(this.name)
        }
    }
}
</script>

 2.组件的自定义事件

 1.组件间的通信方式,适用于:子组件===>父组件

2.使用场景:子组件想给父组件传递数据,那么就要在父组件中给子组件绑定自定义事件(事件回调在A中)

3.绑定自定义事件

  • 在父组件中<Demo @事件名=“方法” />或<Demo v-on:事件名=“方法” />

  • 在父组件中this.$refs.demo.$on('事件名',方法)

4.触发自定义事件this.$emit('事件名',数据)

5.解绑自定义事件this.$off('事件名')

<template>
    <div class="app">
        <h1>{
   
   {msg}}</h1>

        <!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或者v-on) -->
        <Student v-on:atguigu="getStudentName" @demo='m1'/>

        <!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第二种写法,使用ref) -->
        <!-- <Student ref="student"/> -->
    </div>
</template>

<script>
    // 引入School组件
    import Student from './components/Student'
    export default {
        name:'App',
        components:{Student},
        data(){
            return{
                msg:'欢迎学习'
            }
        },
        methods:{
            getStudentName(name){
                console.log('App收到了学生名',name)
            },
            m1(){
                console.log('demo事件被触发了')
            }
        },
        mounted(){
            // this.$refs.student.$on('atguigu',this.getStudentName)
            // this.$refs.student.$once('atguigu',this.getStudentName)
        }
    }
</script>
<style scoped>
    .app{
        background-color: aliceblue;
        padding: 5px;
    }
</style>
//子组件
<template>
    <div class="school">
        <h2>学生姓名:{
   
   {name}}</h2>
        <h2>学生性别:{
   
   {sex}}</h2>
        <button @click="sendStudentName">把学生名给App</button>
        <button @click="unbind">解绑atguigu事件</button>
        <button @click="death">销毁当前Student组件实例</button>
    </div>
</template>

<script>
export default{
    name:'Student',
    data(){
        return{
            name:'四喜',
            sex:'女'
        }
    },
    methods:{
        sendStudentName(){
            //触发Student组件实例身上的atguigu事件
            this.$emit('atguigu',this.name)
            this.$emit('demo')
        },
        unbind(){
            // this.$off('atguigu') //解绑一个自定义事件
            // this.$off(['atguigu','demo']) //解绑多个个自定义事件
            this.$off() //解绑所有自定义事件
        },
        death(){
            this.$destroy()//销毁当前Student组件实例,销毁后student实例的自定义事件全都不奏效
        }
    }
}
</script>

<style scoped>
.school{
        background-color: pink;
    }
</style>

3.全局事件总线

适用于任意组件间的通信

1.定义全局时间总线

2.使用时间总线

  • 接收数据:A组件想接受数据,则在A组件中给$bus绑定自定义事件,时间回调在A组件
  • 提供数据:this.$bus.$emit('xxx',data)

3.最好在beforeDestory钩子中,用$off()去解绑当前组件用到的事件  

 安装全局事件总线(main.js中)

// 引入vue
import Vue from 'vue'
// 引入App
import App from './App.vue'
// 关闭vue的生产提示
Vue.config.productionTip = false

// 创建vm
new Vue({
    el:'#app',
    render: h => h(App),
    beforeCreate(){
        Vue.prototype.$bus = this //安装全局事件总线
    }
})

Student:发出事件

<template>
  <div class="student">
    <h2>学生姓名:{
   
   { name }}</h2>
    <h2>学生性别:{
   
   { sex }}</h2>
    <button @click="sendStudentName">把学生名给School组件</button>
  </div>
</template>

<script>
export default {
  name: "Student",
  data() {
    return {
      name: "张三",
      sex: "男",
    };
  },
  methods: {
    sendStudentName() {
      this.$bus.$emit("hello", this.name);
    },
  },
};
</script>

<style scoped>
.student {
  background-color: pink;
  padding: 5px;
  margin-top: 30px;
}
</style>

School:接收事件

<template>
  <div class="school">
    <h2>学校名称:{
   
   { name }}</h2>
    <h2>学校地址:{
   
   { address }}</h2>
  </div>
</template>

<script>
export default {
  name: "School",
  data() {
    return {
      name: "尚硅谷",
      address: "北京",
    };
  },
  mounted() {
    // console.log('School',this)
    this.$bus.$on("hello", (data) => {
      console.log("我是School组件,收到了数据", data);
    });
  },
  beforeDestroy() {
    this.$bus.$off("hello");
  },
};
</script>

<style scoped>
.school {
  background-color: skyblue;
  padding: 5px;
}
</style>

猜你喜欢

转载自blog.csdn.net/m0_64562972/article/details/127946721