vue2的组件通信方式

组件交互/通信/传值

组件 A 在它的模板中使用了组件 B。它们之间必然需要相互通信:父组件可能要给子组件下发数据,子组件则可能要将它内部发生的事情告知父组件。在 Vue 中,父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息。

1.子组件内使用父组件数据  父-子

1.父组件传递数据给子组件 (可以传递静态属性 动态属性 )

	<my-com title='' :msg='msg' attr-a=''>

2.子组件接收并处理数据

	{

​				props:['title','msg','attrA],

​				template:``

​			}

App.vue

<template>
  <div id="app">
    <Shcool />
    <Student name="科大" :age="19" />
  </div>
</template>

<script>
import Shcool from "./components/Shcool.vue";
import Student from "./components/Student.vue";
export default {
  name: "app",
  components: { Shcool, Student },
};
</script>

<style>
#app {
  background-color: orange;
  padding: 15px;
}
</style>

Student.vue

<template>
  <div id="student">
    <h1>学生姓名:{{ name }}</h1>
    <h1>学生年龄:{{ age + 1 }}</h1>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // studentName: "好学生",
      // age: "18",
    };
  },
  props: ["name", "age"],
};
</script>

<style>
#student {
  background-color: skyblue;
}
</style>

2.父组件内使用子组件的数据

事件发射 自定义事件

在子组件内发射 在父组件内接受

子组件发射时机

1.手动按钮发送

2.监听子组件内数据变化,然后发射

2.1 props实现子传父

props传参同props父传子参数类似,具体实现原理是父组件定义函数,并将函数传递给子组件,在子组件中调用,并将自己的数据作为参数传递给父组件的函数。大体可分为四步。

第一步,在子组件 标签上 上使用v-bind(简写为 :)绑定传递的参数名以及传递的处理函数;

第二步,在子组件的 script 中 添加 props 属性 ,并将 参数名 接收;

第三步,在子组件中调用其他函数来触发用 props接收的参数(也就是那个函数)

第四步,子组件的参数被传递出去

App.vue

<template>
  <div id="app">
    <Shcool :getSchoolName="getSchoolName" />

    <!-- <Student name="科大" :age="19" /> -->
    <Student />
  </div>
</template>

<script>
import Shcool from "./components/Shcool.vue";
import Student from "./components/Student.vue";
export default {
  name: "app",
  components: { Shcool, Student },
  methods: {
    getSchoolName(name) {
      console.log("App收到了学校名:", name);
    },
   
  },
};
</script>

<style>
#app {
  background-color: orange;
  padding: 15px;
}
</style>

School.vue

<template>
  <div id="school">
    <h1>学校名称:{{ name }}</h1>
    <h1>学校地址:{{ addddress }}</h1>
    <button @click="sendSchoolName">把学校名给App</button>
  </div>
</template>

<script>
export default {
 //在子组件的 script 中 添加 props 属性 ,并将 参数名 接收;
  props: ["getSchoolName"],
  data() {
    return {
      name: "科大",
      addddress: "上海",
    };
  },
  methods: {
    sendSchoolName() {
      this.getSchoolName(this.name);
    },
  },
};
</script>
 
<style>
#school {
  background-color: skyblue;
}
</style>

2.2 自定义事件实现子向父传递参数

2.2.1 第一种自定义事件

靠函数参数传递的方法将数据带给父组件,具体分三步:
第一步,在子组件 标签上 上使用v-on(简写为 @)绑定自定义的 事件名 以及对应的处理函数,可以类比原生事件 @click=“handle(e)”;

第二步,在子组件中调用其他函数,使用 this.$emit(‘事件名’,参数) 的方法触发事件;

第三步,子组件的参数被传递出去

App.vue

<template>
  <div id="app">
    <Shcool :getSchoolName="getSchoolName" />

    <!-- <Student name="科大" :age="19" /> -->
    <Student v-on:lili="getStudentName" />
  </div>
</template>

<script>
import Shcool from "./components/Shcool.vue";
import Student from "./components/Student.vue";
export default {
  name: "app",
  components: { Shcool, Student },
  methods: {
    getSchoolName(name) {
      console.log("App收到了学校名:", name);
    },
    getStudentName(name) {
      console.log("App收到学生名:", name);
    },
  },
};
</script>

<style>
#app {
  background-color: orange;
  padding: 15px;
}
</style>

Student.vue

<template>
  <div id="student">
    <h1>学生姓名:{{ name }}</h1>
    <h1>学生年龄:{{ age }}</h1>
    <button @click="sendStudentName">把学生名给App</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      name: "好学生",
      age: "18",
    };
  },
  // props: ["name", "age"],

  methods: {
    sendStudentName() {
      this.$emit("lili", this.name);
    },
  },
};
</script>

<style>
#student {
  background-color: skyblue;
}
</style>

2.2.2 第二种自定义事件

Student组件不需要任何变化
主要变动有两处,第一处 是子组件标签中 使用ref属性;第二处 是不在methods或者watch中 定义处理函数,而是在生命周期函数中处理。
这样的好处是更加灵活,自定义事件可以添加其他异步操作,且对子组件绑定多个自定义事件时,也无需考虑太多的逻辑,不断地在 生命周期函数中 使用 $on 来处理即可。

 $on 接收两个参数,$on(自定义事件名,函数) 而函数可以用箭头函数来简写操作

注意:通过this.$refs.xxx.$on('atguigu',回调)绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!

App.vue

<template>
  <div class="app">
    <h1>{{ msg }}</h1>
    <!-- 通过父组件给子组件传递函数类型的props实现:子给父传递数据
     -->
    <School :getSchoolName="getSchoolName" />
    <hr />

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

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

<script>
import Student from "./components/Student.vue";
import School from "./components/School.vue";

export default {
  name: "App",
  components: { Student, School },
  data() {
    return {
      msg: "你好啊",
    };
  },
  methods: {
    getSchoolName(name) {
      console.log("App收到了学校名:", name);
    },
    getStudentName(name) {
      console.log("App收到了学生名:", name);
    },
  },
  mounted() {
    this.$refs.student.$on("lili", this.getStudentName);
  },
};
</script>
<style scoped>
.app {
  background-color: gold;
  padding: 10px;
}
</style>

3 全局事件总线(GlobalEventBus)

全局事件总线是一种可以在任意组件间通信的方式,本质上就是一个对象。它必须满足以下条件:

  1. 所有的组件对象都必须能看见他
  2. 这个对象必须能够使用$on$emit$off方法去绑定、触发和解绑事件

main.js

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

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

App.vue

<template>
  <div class="app">
    <School />
    <Student />
  </div>
</template>

<script>
import Student from "./components/Student.vue";
import School from "./components/School.vue";

export default {
  name: "App",
  components: { Student, School },
  data() {
    return {};
  },
};
</script>
<style scoped>
.app {
  background-color: rgb(241, 207, 11);
  padding: 10px;
}
</style>

Student.vue

<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("demo", this.name);
    },
  },
};
</script>
<style  scoped>
.student {
  background-color: red;
}
</style>

School.vue

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

<script>
export default {
  name: "School",

  data() {
    return {
      name: "科大",
      address: "北京",
    };
  },
  methods: {
    demo(data) {
      console.log("我是School组件,收到了数据:", data);
    },
  },
  mounted() {
    this.$bus.$on("demo", this.demo);
  },
  beforeDestroy() {
    this.$bus.$off("demo");
  },
};
</script>
<style >
.dome {
  background-color: skyblue;
}
</style>

总结:

全局事件总线(GlobalEventBus):

  1. 一种组件间通信的方式,适用于任意组件间通信
  2. 安装全局事件总线:

new Vue({
   	...
   	beforeCreate() {
   		Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm
   	},
    ...
})

使用事件总线:

  1. 接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身

export default {
    methods(){
        demo(data){...}
    }
    ...
    mounted() {
        this.$bus.$on('xxx',this.demo)
    }
}

2.提供数据:`this.$bus.$emit('xxx',data)`

最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件

4  消息的订阅预发布

School.vue

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

<script>
import pubsub from "pubsub-js";
export default {
  name: "School",

  data() {
    return {
      name: "科大",
      address: "北京",
    };
  },
  methods: {
    demo(msgName, data) {
      console.log("我是School组件,收到了数据:", data);
    },
  },
  mounted() {
    this.pubId = pubsub.subscribe("demo", this.demo); //订阅消息
  },
  beforeDestroy() {
    pubsub.unsubscribe(this.pubId); //取消订阅
  },
};
</script>
<style >
.dome {
  background-color: skyblue;
}
</style>

Student.vue

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

<script>
import pubsub from "pubsub-js";
export default {
  name: "Student",
  data() {
    return {
      name: "好学生",
      sex: "男",
    };
  },
  methods: {
    sendStudentName() {
      // this.$bus.$emit("demo", this.name);
      pubsub.publish("demo", this.name); //发布消息
    },
  },
};
</script>
<style  scoped>
.student {
  background-color: red;
}
</style>

总结:

消息订阅与发布(pubsub):

消息订阅与发布是一种组件间通信的方式,适用于任意组件间通信

使用步骤:

安装pubsub:npm i pubsub-js

引入:import pubsub from 'pubsub-js'

接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身

export default {
    methods(){
        demo(data){...}
    }
    ...
    mounted() {
		this.pid = pubsub.subscribe('xxx',this.demo)
    }
}

提供数据:pubsub.publish('xxx',data)

最好在beforeDestroy钩子中,使用pubsub.unsubscribe(pid)取消订阅

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值