Vue2中父子組件通信的幾種常用方法


源碼地址

點擊查看演示源碼

Vue2父子傳參:props

首先在父組件中引入子組件,然后以屬性的方式將數據傳遞給子組件

父組件:

<template>
	<div class="home">
        <!-- 在子組件中使用 :變量名=value  的方式向子組件傳遞數據,子組件通過 props 接收-->
        <HelloWorld :msg="fatchData" ref="childEl"/>       
    </div>
</template>

<script>
    // @ is an alias to /src
    import HelloWorld from '@/components/HelloWorld.vue'

    export default {
        name: 'Home',
        components: {
            HelloWorld
        },
        data () {
            return {
                fatchData: '我是父組件通過props傳遞給子組件的文字'
            }
        }        
    }
</script>

然后在子組件中使用props接收,props里定義的名字要和父組件定義的一致

子組件:

<template>
	<div>
        <span>{{ msg }}</span>
    </div>
</template>

<script>
    export default {
        name: 'HelloWorld',
        // 子組件通過使用 props 接收父組件傳遞過來的數據
        props: {
            msg: String
        }
  }
</script>

Vue2父子傳參之父傳子:$refs

在父組件中給子組件的標簽上添加 ref 等於一個變量,然后通過使用 $refs 可以獲取子組件的實例,以及調用子組件的方法和傳遞參數

父組件:

<template>
	<div class="home">
        <!-- 在子組件中使用 :變量名=value  的方式向子組件傳遞數據,子組件通過 props 接收-->
        <HelloWorld :msg="fatchData" ref="childEl"/>
        <div>
            父組件
        </div>
        <div>
            <button @click="changeChildMsg">父組件按鈕</button>
        </div>
    </div>
</template>
<script>
    import HelloWorld from '@/components/HelloWorld.vue'
    export default {
        name: 'Home',
        components: {
            HelloWorld
        },
        data () {
            return {
                fatchData: '我是父組件通過props傳遞給子組件的文字'
            }
        },
        methods: {
            // 點擊父組件的按鈕修改子組件中顯示的文字
            changeChildMsg () {
                this.fatchData = '通過按鈕修改了子組件中顯示的問題'
                // 父組件調用子組件的方法並傳遞參數
                this.$refs.childEl.showText('我來自父組件')
            }
        }
    }
</script>

然后在子組件中定義相同的方法名,在父組件使用 $refs 調用后觸發在子組件中定義的同名方法

子組件:

<template>
    <div class="hello">
        <b>子組件</b>
        <div>
        	<span>{{ msg }}</span>
        </div>
        <div>
       	 	<button>子組件按鈕</button>
        </div>
    </div>
</template>

        <script>
        export default {
        name: 'HelloWorld',
        // 子組件通過使用 props 接收父組件傳遞過來的數據
        props: {
            msg: String
        },
        methods: {
            // 這個方法由父組件通過 this.$refs.childEl.showText('我來自父組件') 調用觸發
            showText (text) {
                alert(text)
            }
        }
    }
</script>

Vue2父子傳參之子傳父:$emit

在子組件中我們也可以調用父組件的方法向父組件傳遞參數,通過$emit來實現

子組件:

<button @click="childClick">子組件按鈕</button>

<script>
export default {
  name: 'HelloWorld',
  methods: {
    // 子組件通過 $emit 調用父組件中的方法
    childClick () {
      this.$emit('setValueName', '我是通過子組件傳遞過來的')
    }
  }
}
</script>

然后在父組件中定義並綁定子組件傳遞的 setValueName 事件,事件名稱要和子組件定義的名稱一樣

父組件:

<HelloWorld  @setValueName="setValueName" />

<script>
import HelloWorld from '@/components/HelloWorld.vue'
export default {
  name: 'Home',
  components: {
    HelloWorld
  },
  methods: {
    // 該方法是由子組件觸發的
    setValueName (data) {
      alert(data) //= > 我是通過子組件傳遞過來的
    }
  }
}
</script>

Vue2父子傳參:parent/children

  • 父組件通過$children獲取子組件的實例數組
  • 子組件通過$parent獲取的父組件實例

父組件中可以存在多個子組件,所以this.$children獲取到的是子組件的數組

父組件:

<HelloWorld />
<button @click="getSon">children/parent</button>

<script>
import HelloWorld from '@/components/HelloWorld.vue'

export default {
  name: 'Home',
  components: {
    HelloWorld
  },
  data () {
    return {
      parentTitle: '我是父組件'
    }
  },
  methods: {
    // 子組件調用這個方法
    parentHandle () {
      console.log('我是父組件的方法')
    },
    // 通過 this.$children 獲取子組件實例
    getSon () {
      console.log(this.$children)
      console.log(this.$children[0].sonTitle) //= > 我是子組件
      this.$children[0].sonHandle() //= > 我是子組件的方法
    }
  }
}
</script>

子組件:

<button @click="getParent">獲取父組件的方法和值</button>
<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      sonTitle: '我是子組件'
    }
  },
  methods: {
    // 父組件通過 this.$children 來調用
    sonHandle () {
      console.log('我是子組件的方法')
    },
    // 調用父組件的方法和獲取父組件的值
    getParent () {
      console.log(this.$parent)
      console.log(this.$parent.parentTitle) //= > 我是父組件
      this.$parent.parentHandle() //= > 我是父組件的方法
    }
  }
}
</script>

Vue2兄弟傳參:bus.js

首先新建 bus.js 文件,初始化如下代碼:

import Vue from 'vue'
export default new Vue()

然后在需要通信的組件中都引入該 bus 文件,其中一個文件用來發送,一個文件監聽接收。派發事件使用 bus.$emit

下面組件派發了一個叫setYoungerBrotherData的事件

<template>
  <div>
    哥哥組件:<button @click="setYoungerBrotherData">給弟弟傳參</button>
  </div>
</template>
<script>
import bus from '../assets/bus'
export default {
  methods: {
    setYoungerBrotherData () {
      // 通過 bus.$emit 派發一個事件
      bus.$emit('setYoungerBrotherData', '給弟弟傳參')
    }
  }
}
</script>

在另一個頁面中使用 bus.$on('setYoungerBrotherData',()=>{}) 監聽

<template>
  <div>弟弟組件:{{ msg }}</div>
</template>
<script>
import bus from '../assets/bus'
export default {
  data () {
    return {
      msg: ''
    }
  },
  mounted () {
    // 通過 bus.$on 監聽兄弟組件派發的方法
    bus.$on('setYoungerBrotherData', (res) => {
      this.msg = res
    })
  }
}
</script>

Vue2跨級傳參:provide/inject

provideinjectvue生命周期上的兩個函數,這對選項需要一起使用,以允許一個祖先組件向其所有子孫后代注入一個依賴,不論組件層次有多深,並在其上下游關系成立的時間里始終生效。

提示:provideinject 綁定並不是可響應的。這是刻意為之的。然而,如果你傳入了一個可監聽的對象,那么其對象的 property 還是可響應的。

祖先組件:

<script>
    export default {
        name: 'Home',
        // 通過 provide 提供的數據可以在該組件層次之下的任何組件使用
        provide () {
            return {
                // 可以傳遞普通字符串
                provideName: '祖先',
                // 也可以傳遞一個異步方法
                getOrderInfo: () => {
                    return this.getOrderList()
                }
            }
        },
        methods: {
            // 傳遞一個異步方法獲取數據,用來模擬接口請求
            getOrderList () {
                return new Promise((resolve, reject) => {
                    // 倒計時兩秒模擬請求延遲
                    setTimeout(() => {
                        resolve({
                            code: 'WX15485613548',
                            name: '農夫安裝工單'
                        })
                    }, 2000)
                })
            }
        }
    }
</script>

孫子組件:

<template>
<div>
    {{ bar }}
    <button @click="getOrder">異步獲取數據</button>
    </div>
</template>
<script>
    export default {
        // 使用 inject 接收祖先生成的數據
        inject: ['provideName', 'getOrderInfo'],
        data () {
            return {
                // inject 接收的數據可以作為數據的入口
                bar: this.provideName
            }
        },
        mounted () {
            console.log(this.provideName) //= >祖先
        },
        methods: {
            getOrder () {
                // 調用的是父組件的方法,延遲兩秒獲取數據
                this.getOrderInfo().then(res => {
                 	 console.log(res) //= > {code: "WX15485613548", name: "農夫安裝工單"}
                })
            }
        }
    }
</script>

使用 provide/inject的好處是父組件不需要知道是哪個自組件使用了我的數據,子組件也不需要關心數據從何而來

總結

  • 父子通信:父向子傳遞數據通過props,子向父傳遞數據通過$emit事件,父鏈子鏈使用$parent/$children,直接訪問子組件實例使用$refs
  • 兄弟通信:bus,Vuex
  • 跨級通信:bus,Vuex,provide/inject


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM