?Vue組件之間的通信方式(個人理解)
1. props(父傳子)
```
? //父組件 parent.vue
? <template>
? ? ? //子組件
? ? ? <child-com :num="num" :str="str" :obj="obj" :func="func" />
? </tempalte>
? //引入子組件
? import ChildCom from './components/child';
? export default{
? ? components:{ChildCom},
? ? data(){
? ? ? return {
? ? ? ? ? num:25,
? ? ? ? ? str:'這是一個字符串類型的父組件傳遞的值',
? ? ? ? ? obj:{
? ? ? ? ? ? ? attr:'一個對象中的屬性值'
? ? ? ? ? }
? ? ? }
? ? },
? ? methods:{
? ? ? func(){
? ? ? ? ? console.log('這是一個父組件的方法膛壹,可以由子組件通過props方式調(diào)用');
? ? ? }
? ? }
? }
? //子組件 child.vue
? export default{
? ? ? props:{
? ? ? ? ? num:{
? ? ? ? ? ? ? type:Number//num的類型為---數(shù)字類型
? ? ? ? ? },
? ? ? ? ? str:{
? ? ? ? ? ? ? type:String,//str的類型為---字符串類型
? ? ? ? ? ? ? default:'hello default value'//str的默認(rèn)值
? ? ? ? ? },
? ? ? ? ? obj:{
? ? ? ? ? ? ? type:Object,//obj的類型為---對象類型
? ? ? ? ? ? ? reqired:true//是否必傳的參數(shù),布爾值true:必須傳這個參數(shù) ,默認(rèn)為false:不是必傳
? ? ? ? ? },
? ? ? ? ? func:{
? ? ? ? ? ? ? type:Function, //func的類型為---函數(shù)
? ? ? ? ? ? ? default(){? //不傳遞時默認(rèn)值
? ? ? ? ? ? ? ? ? return ()=>{}
? ? ? ? ? ? ? }
? ? ? ? ? }
? ? ? },
? ? ? data(){
? ? ? ? return{}
? ? ? },
? ? ? mounted(){
? ? ? ? console.log(this.num);
? ? ? ? //控制臺輸出:25
? ? ? ? console.log(this.str);
? ? ? ? //控制臺輸出:這是一個字符串類型的父組件傳遞的值
? ? ? ? console.log(this.obj);
? ? ? ? //控制臺輸出:{attr:'一個對象中的屬性值'}
? ? ? ? this.func();
? ? ? ? //調(diào)用parent的func方法
? ? ? ? //控制臺輸出:這是一個父組件的方法,可以由子組件通過props方式調(diào)用
? ? ? }
? }
```
2. v-on/this.$emit('方法名','參數(shù)');(父傳子,子通過調(diào)用父傳來的方法回傳參數(shù))
```
//(父傳子龄恋,子通過調(diào)用父傳來的方法回傳參數(shù))
//父組件: @childMethod="parentMethod"?
//子組件: this.$emit('方法名',參數(shù))
//childMethod:child子組件中this.$emit('childMethod',參數(shù))
//parentMethod:parent父組件中的要被子組件調(diào)用的方法名
? //父組件 parent.vue
? <template>
? ? ? //子組件
? ? ? <child-com :num="num" :str="str" :obj="obj" @func="func" />
? </tempalte>
? //引入子組件
? import ChildCom from './components/child';
? export default{
? ? components:{ChildCom},
? ? data(){
? ? ? return {
? ? ? ? ? num:25,
? ? ? ? ? str:'這是一個字符串類型的父組件傳遞的值',
? ? ? ? ? obj:{
? ? ? ? ? ? ? attr:'一個對象中的屬性值'
? ? ? ? ? }
? ? ? }
? ? },
? ? methods:{
? ? ? func(arguments){
? ? ? ? ? console.log('這是一個父組件的方法,可以由子組件通過props方式調(diào)用',arguments);
? ? ? }
? ? }
? }
? //子組件 child.vue
? export default{
? ? ? props:{
? ? ? ? ? num:{
? ? ? ? ? ? ? type:Number//num的類型為---數(shù)字類型
? ? ? ? ? },
? ? ? ? ? str:{
? ? ? ? ? ? ? type:String,//str的類型為---字符串類型
? ? ? ? ? ? ? default:'hello default value'//str的默認(rèn)值
? ? ? ? ? },
? ? ? ? ? obj:{
? ? ? ? ? ? ? type:Object,//obj的類型為---對象類型
? ? ? ? ? ? ? reqired:true//是否必傳的參數(shù),布爾值true:必須傳這個參數(shù) 患雏,默認(rèn)為false:不是必傳
? ? ? ? ? }
? ? ? },
? ? ? data(){
? ? ? ? return{}
? ? ? },
? ? ? mounted(){
? ? ? ? console.log(this.num);
? ? ? ? //控制臺輸出:25
? ? ? ? console.log(this.str);
? ? ? ? //控制臺輸出:這是一個字符串類型的父組件傳遞的值
? ? ? ? console.log(this.obj);
? ? ? ? //控制臺輸出:{attr:'一個對象中的屬性值'}
? ? ? ? this.$emit('func',參數(shù));
? ? ? ? //調(diào)用parent的func方法
? ? ? ? //控制臺輸出:這是一個父組件的方法,可以由子組件通過props方式調(diào)用,參數(shù)
? ? ? }
? }
```
3. this.$refs.child.method(arguments);(父傳子)
```
//child:為子組件ref注冊的名字罢维,可自行命名
//method:為子組件中的方法名
? //父組件 parent.vue
? <template>
? ? ? //子組件
? ? ? <child-com ref="child" />
? </tempalte>
? //引入子組件
? import ChildCom from './components/child';
? export default{
? ? components:{ChildCom},
? ? data(){
? ? ? ? return{}
? ? }
? ? methods:{
? ? ? func(){
? ? ? ? this.$refs.child.childMethod();
? ? ? ? //控制臺輸出:我是子組件的方法淹仑,父組件通過this.$refs.child.childMethod()調(diào)用
? ? ? }
? ? }
? }
? //子組件 child.vue
? export default{
? ? props:{},
? ? data(){
? ? ? return{}
? ? },
? ? mounted(){},
? ? methods:{
? ? ? childMethod(){
? ? ? ? console.log('我是子組件的方法,父組件通過this.$refs.child.childMethod()調(diào)用');
? ? ? }
? ? }
? }
```
4. this.$parent.$parent.func(arguments);(子傳父)
```
//父組件的fun方法
? //父組件 parent.vue
? <template>
? ? ? //子組件
? ? ? <child-com? />
? </tempalte>
? //引入子組件
? import ChildCom from './components/child';
? export default{
? ? components:{ChildCom},
? ? data(){
? ? ? return {}
? ? },
? ? methods:{
? ? ? func(arguments){
? ? ? ? ? console.log('這是一個父組件的方法肺孵,可以由子組件通過this.$parent.$parent(參數(shù))方式調(diào)用',arguments);
? ? ? }
? ? }
? }
? //子組件 child.vue
? export default{
? ? ? props:{ },
? ? ? data(){
? ? ? ? return{}
? ? ? },
? ? ? mounted(){
? ? ? this.$parent.$parent.func('參數(shù)');
? ? ? ? //調(diào)用parent的func方法
? ? ? ? //控制臺輸出:這是一個父組件的方法匀借,可以由子組件通過this.$parent.$parent(參數(shù))方式調(diào)用,參數(shù)
? ? ? }
? }
```
5. this.$attrs:里面包含所有父組件中不作為 prop傳遞的屬性∑骄剑可以進(jìn)行跨級的參數(shù)傳遞
```
//(父傳子---屬性)
//可修改this.$atrrs里的屬性值
? //父組件 parent.vue
? <template>
? ? <child-com str="這是一個不通過prop傳遞的字符串" :strProp="strProp" />
? </template>
? export default {
? ? data(){
? ? ? return {
? ? ? ? ? strProp:"這是一個通過prop傳遞的字符串"
? ? ? }
? ? },
? }
? //子組件 child.vue
? <tempalte>
? ? <grand-child v-bind="$attrs" /> //針對向下級組件傳遞
? </temaplate>
? import GrandChildCom from './grandchild';
? export default {
? ? components:{GrandChildCom},
? ? props:{
? ? ? ? strProp:{
? ? ? ? ? ? type:String,
? ? ? ? ? ? default:''
? ? ? ? }
? ? },
? ? data(){
? ? ? ? return {}
? ? },
? ? mounted(){
? ? ? ? console.log(this.$atrrs);//{str:'這是一個不通過prop傳遞的字符串'}
? ? ? ? console.log(this.strProp);//這是一個通過prop傳遞的字符串
? ? }
? }
? //孫子組件GrandChild.vue
? export default {
? ? props:{
? ? ? ? strProp:{
? ? ? ? ? ? type:String,
? ? ? ? ? ? default:''
? ? ? ? }
? ? },
? ? data(){
? ? ? ? return {}
? ? },
? ? mounted(){
? ? ? ? console.log(this.$atrrs);//{str:'這是一個不通過prop傳遞的字符串'}
? ? ? ? console.log(this.strProp);//這是一個通過prop傳遞的字符串
? ? }
? }
```
6. this.$listeners:包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監(jiān)聽器
```
//(父傳子---方法吓肋,子通過調(diào)用父傳來的方法回傳參數(shù))
//this.$listeners
? //父組件 parent.vue
? <template>
? ? <child-com @handleUpdate="handleUpdate" @handleAdd.native="handleAdd" />
? </template>
? export default {
? ? data(){
? ? ? return {}
? ? },
? ? methods:{
? ? ? ? handleUpdate(val){
? ? ? ? ? ? console.log('這是handleUpdate的日志',val);
? ? ? ? },
? ? ? ? handleAdd(){
? ? ? ? ? ? console.log('這是handleAdd的日志');
? ? ? ? },
? ? }
? }
? //子組件 child.vue
? <tempalte>
? ? <grand-child-com v-on="$listeners" /> //針對向下級組件傳遞
? </temaplate>
? import GrandChildCom from './grandchild';
? export default {
? ? components:{GrandChildCom},
? ? props:{},
? ? data(){
? ? ? ? return {}
? ? },
? ? mounted(){
? ? ? ? console.log(this.$listeners);//{handleUpdate:f}
? ? ? ? console.log(this.$listeners.handleUpdate('child調(diào)用的'));//這是handleUpdate的日志,child調(diào)用的
? ? }
? }
? //孫子組件GrandChild.vue
? export default {
? ? props:{
? ? ? ? strProp:{
? ? ? ? ? ? type:String,
? ? ? ? ? ? default:''
? ? ? ? }
? ? },
? ? data(){
? ? ? ? return {}
? ? },
? ? mounted(){
? ? ? ? console.log(this.$listeners);//{handleUpdate:f}
? ? ? ? console.log(this.$listeners.handleUpdate('grandChild調(diào)用的'));//這是handleUpdate的日志,grandChild調(diào)用的
? ? }
? }
```
7. provide/inject(選項 / 組合):允許一個祖先組件向其所有子孫后代注入一個依賴,可以注入屬性和方法瑰艘,從而實現(xiàn)跨級父子組件通信
```
//(父傳子---依賴是鬼,子通過調(diào)用父傳來的方法回傳參數(shù))
// provide/inject
? //父組件 parent.vue
? <template>
? ? <child-com? />
? </template>
? export default {
? ? data(){
? ? ? return {
? ? ? ? ? name:'Hello Xiaoer'
? ? ? }
? ? },
? ? provide() {
? ? ? return {
? ? ? ? provideName: {
? ? ? ? ? name: this.name,
? ? ? ? ? change: (val) => {
? ? ? ? ? ? console.log( val )
? ? ? ? ? }
? ? ? ? }
? ? ? }
? ? }
? }
? //子組件 child.vue
? <tempalte>
? ? <grand-child-com? /> //針對向下級組件傳遞
? </temaplate>
? import GrandChildCom from './grandchild';
? export default {
? ? components:{GrandChildCom},
? ? props:{},
? ? data(){
? ? ? ? return {}
? ? },
? ? inject: ['provideName'],
? ? mounted(){
? ? ? ? console.log(this.provideName.name);//控制臺輸出:Hello Xiaoer
? ? ? ? this.provideName.change('變化函數(shù)');//控制臺輸出:變化函數(shù)
? ? },
? }
? //孫子組件GrandChild.vue
? export default {
? ? props:{},
? ? data(){
? ? ? ? return {}
? ? },
? ? inject: ['provideName'],
? ? mounted(){
? ? ? ? console.log(this.provideName.name);//控制臺輸出:Hello Xiaoer
? ? ? ? this.provideName.change('變化函數(shù)');//控制臺輸出:變化函數(shù)
? ? },
? }
```
8. EventBus:(第三方庫)甚至任意2個組件間通信(任意組件)
```
[github地址](https://github.com/krasimir/EventBus)
//通過導(dǎo)出一個 Vue 實例肤舞,然后再需要的地方引入:
? ? // eventBus.js
? ? import Vue from 'vue'export
? ? const EventBus = new Vue()
? ? //使用 EventBus 訂閱和發(fā)布消息:
? ? import {EventBus} from '../utils/eventBus.js'
? ? // 訂閱消息(接受更新后需要做點什么的組件)
? ? EventBus.$on('update', val => {})
? ? // 發(fā)布消息(負(fù)責(zé)更新的組件)
? ? EventBus.$emit('update', '更新信息')
```
```
//在main.js中初始化一個全局的事件:
? ? // main.js
? ? Vue.prototype.$eventBus = new Vue()
? ? //index.vue
? ? // 訂閱消息(接受更新后需要做點什么的組件)
? ? this.$eventBus.$on('update', val => {})
? ? // 發(fā)布消息(負(fù)責(zé)更新的組件)
? ? this.$eventBus.$emit('update', '更新信息')
```
```
//移除事件監(jiān)聽
? ? this.$eventBus.$off('update', {})
```