- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) > web開(kāi)發(fā) > JavaScript >
- 超詳細的vue組件間通信總結
組件通信在我們平時(shí)開(kāi)發(fā)過(guò)程中,特別是在vue和在react中,有著(zhù)舉足輕重的地位。本篇將總結在vue中,組件之間通信的幾種方式:
father.vue:
<template> <div> <div>我是父親:<input type="button" value="父親" /> 數字為: {{num}}</div> <son :num="num" @change="change"></son> </div> </template> <script> import son from "./son.vue"; export default { name: "Father", components: { son, }, data() { return { num: 1, }; }, methods:{ change(val){ this.num = val } } }; </script>
son.vue:
<template> <div>我是兒子:<input type="button" value="兒子" @click="change"/>數字為:{{num}}</div> </template> <script> export default { name: "App", components: {}, props: { num: { default: 0, }, }, created() {}, methods: { change(){ // this.num = 2 props通信是單向數據流,在這直接修改父組件傳過(guò)來(lái)的num將會(huì )報錯 // 可以用$emit觸發(fā)change事件,father組件綁定change事件 this.$emit('change', 2) } }, }; </script>
對于上面的場(chǎng)景:子組件的change事件只是為了修改父組件中某一個(gè)值,還可以有以下幾種寫(xiě)法:
1.父組件綁定給子組件的事件使用箭頭函數
father: <son :num="num" @change="val => num = val"></son> son: this.$emit('change', 2)
2.update:num和.sync
father: <son :num.sync="num"></son> son: this.$emit('update:num', 2)//update是規定的寫(xiě)法,不可更換
3.v-model
先修改props和綁定的事件:
father:<son :value="num" @input="val => num = val"></son>son:this.$emit('input', 2) 可用v-model簡(jiǎn)寫(xiě):<son v-model="num"></son>
$parent、$children可直接在父子組件中調用各自的方法以及修改數據
子組件中直接:this.$parent.num = 2
父組件中$children是個(gè)數組,因此具體是哪個(gè)子組件不太直觀(guān),可以用$refs來(lái)操作子組件
vue官方并不推薦使用這種通信方式:節制地使用$parent
和$children
- 它們的主要目的是作為訪(fǎng)問(wèn)組件的應急方法,更推薦用 props 和 events 實(shí)現父子組件通信。
$attrs可以拿到父組件傳過(guò)來(lái)的屬性:
<div>我是兒子:<input type="button" value="兒子" @click="change"/>數字為:{{$attrs}}</div>
dom節點(diǎn):
$attrs會(huì )直接將傳過(guò)來(lái)的屬性放到對應的標簽上,反觀(guān)props就不會(huì )。如果想去掉標簽中的這些屬性,可以用inheritAttrs:
值得注意的是:props的優(yōu)先級大于$attrs,即當props存在的時(shí)候,$attrs為空對象:
$attrs常用于跨多級組件傳遞屬性,比如祖孫組件,用父組件做中轉:
father:
<son v-bind="$attrs"></son>
$attrs用于屬性跨級傳遞,方法跨級傳遞則用$listeners。
grandFather.vue:
<template> <div> <div>我是祖父: 數字為:{{nums}}</div> <father :nums="nums" @up="up" @down="down"></father> </div> </template> <script> import father from "./father.vue"; export default { name: "App", components: { father, }, data(){ return { nums:0 } }, methods: { up() { alert('up') }, down() { alert('down') }, }, }; </script>
father.vue:
<son v-bind="$attrs" v-on="$listeners"></son>
son.vue:
<div>我是兒子:<input type="button" value="兒子" @click="$listeners.up"/></div>
這對選項需要一起使用,以允許一個(gè)祖先組件向其所有子孫后代注入一個(gè)依賴(lài),不論組件層次有多深,并在其上下游關(guān)系成立的時(shí)間里始終生效
provide選項應該是一個(gè)對象或返回一個(gè)對象的函數。
inject選項應該是一個(gè)字符串數組或一個(gè)對象。
App:
... export default { provide(){ return {vm: this} }, ...
son:
... export default { inject: ['vm'], data(){}, mounted(){ console.log(this.vm) } ...
注意:provide 和 inject 綁定并不是可響應的。這是刻意為之的。然而,如果你傳入了一個(gè)可監聽(tīng)的對象,那么其對象的 property 還是可響應的。
inject注入中的值會(huì )沿著(zhù)組件向上查找,遵從"就近原則"。
provide 和 inject中的數據流是雙向的。
eventBus通過(guò)發(fā)布訂閱全局事件,供其他組件使用。
在main.js中:
Vue.prototype.$bus = new Vue();
parent.vue:
<template> <div> <son1></son1> <son2></son2> </div> </template> <script> import son1 from './son1.vue' import son2 from './son2.vue' export default { name: 'parent', components: { son1, son2 }, created(){ this.$bus.$on('busEvent',(v)=>{ console.log(v); }) }, beforeDestroy(){ this.$bus.off('busEvent') } } </script>
son1和son2中的mounted:
son1:mounted(){ this.$bus.$emit('busEvent','son1哈哈') }son2:mounted(){ this.$bus.$emit('busEvent', 'son2嘻嘻')}
打印結果:
使用eventBus有三點(diǎn)需要注意,1.$bus.on應該在created鉤子內使用,如果在mounted使用,它可能接收不到其他組件來(lái)自created鉤子內發(fā)出的事件;
2.$bus.emit應該在mounted中使用,等待created中的$bus.on事件綁定完成;
3.發(fā)布訂閱的事件在beforeDestory鉤子里需要使用$bus.off解除,組件銷(xiāo)毀后沒(méi)必要一直監聽(tīng)。
借助vuex的狀態(tài)管理來(lái)實(shí)現組件通信,vuex適用于較為復雜的項目,頻繁的數據共享且數據量比較大。
store/index.js:
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vuex.Store({ state: { isLogin: false }, mutations: { loginState (state, isLogin) { state.isLogin = isLogin } } }) export default store
App.vue:
created(){ this.$store.commit('loginState',true)// 設置登錄狀態(tài)為true },
son.vue:
<template> <div>我是兒子:<input type="button" value="兒子" />登錄狀態(tài):{{isLogin}}</div> </template> <script> import {mapState} from 'vuex'; export default { name: "son", computed:{ ...mapState(['isLogin']) } }; </script>
localstorage是瀏覽器的本地存儲,將會(huì )長(cháng)期存儲在瀏覽器中,非常龐大的數據不建議用此方式。
App.vue
created(){ localStorage.setItem('isLogin', true) },
son.vue:
computed:{ isLogin(){ return localStorage.getItem('isLogin') } }
常見(jiàn)的組件通信方式基本就是這些啦,有什么遺漏或不足的,歡迎評論區留言!
到此這篇關(guān)于vue組件間通信的文章就介紹到這了,更多相關(guān)vue組件間通信內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站