閱讀時間預估:8分鐘
前端
組件之間通訊是Vue中最經常使用,最基礎的部分,一般組件以前的通訊分爲如下幾種:vue
props $emit v-on
父組件A經過props向子組件B通訊git
接下來咱們經過一個例子來加深以上理解:程序員
自定義一個Son.vue子組件,引入到父組件中 在父組件中定義一個數據github
<template>
<div id="app">
<!-- 前者自定義名稱便於子組件調用,後者要傳遞數據名 -->
<son v-bind:user="user"></son>
</div>
</template>
複製代碼
<script>
import Son from './components/Son'
export default {
name: 'app',
components: {
Son,
},
data () {
return { // 父組件定義數據,傳遞給子組件
user: ["james", "alice", "joho"]
}
},
}
</script>
複製代碼
子組件中經過prop來定義父組件傳值的值類型,是不是必須以及默認值vuex
<script>
export default {
components: {
},
data () {
return {
};
},
computed: {
},
methods: {
},
props: {
user: { //這個就是父組件中子標籤自定義名字
type: Array,
required: true,
default: []
}
},
}
</script>
複製代碼
而後在適當的位置將父組件傳遞過來的數據進行渲染npm
<template>
<div>
<ul>
<li v-for="(item,index) in user"
:key="index">姓名:{{item}}</li>
</ul>
</div>
</template>
複製代碼
瀏覽器打開會顯示user裏面的值.瀏覽器
總結:父組件經過props向下傳遞數據給子組件。注:組件中的數據共有三種形式:data、props、computedbash
核心點app
1.子組件使用this.$emit('fn',param)
向父組件傳值
2.父組件經過v-on:fn="fn"
來接受子組件傳遞過來的值
子組件中:
子組件包含一個點擊事件
// 定義一個點擊事件
<son v-bind:user="user"
@titleChange="changeTitle">
</son>
複製代碼
在點擊事件中經過this.$emit()來傳遞事件
<script>
//import x from ''
export default {
components: {
},
data () {
return {
title: '我是子組件',
toParentData: '我是子組件傳遞的數據'
};
},
computed: {
},
methods: {
btnClick () {
this.$emit('titleChange', this.toParentData);
}
},
}
</script>
複製代碼
父組件中: 經過v-on來接受子組件發出的事件名稱:titleChange而且和本身的changeTitle事件綁定
<template>
<div id="app">
<!-- 前者自定義名稱便於子組件調用,後者要傳遞數據名 -->
<son v-bind:user="user"
v-on:titleChange="changeTitle"></son>
<p>{{msg}}</p>
</div>
</template>
複製代碼
實現changeTitle方法,改變data中的msg數據
<script>
import Son from './components/Son'
export default {
name: 'app',
components: {
Son,
},
data () {
return {
user: ["james", "alice", "joho"],
msg: '我是父組件顯示的內容'
}
},
methods: {
changeTitle (title) {
this.msg = title;
}
}
}
</script>
複製代碼
總結:子組件經過events給父組件發送消息,實際上就是子組件把本身的數據發送到父組件。
發現了一個問題,若是孫子組件給爺爺組件傳值,經過props
或者$emit
方式是一件很痛苦的事情,須要經過中間的爸爸來作銜接,這樣通訊顯然會使得組件耦合,同時兄弟組件間的通訊props
,$emit
也實現不了?那麼問題來了,如何解決呢?
這裏介紹中央事件總線的方式,名字高大上其實就是抽一個公共Vue實例媒介來管理,須要通訊的組件都引入Bus,以後經過分別觸發和監聽 Bus 事件,進而實現組件之間的通訊和參數傳遞.
// Bus.js
import Vue from 'vue'
export default new Vue;
複製代碼
// ComponentA.vue
<template>
<div>
<b>組件A:</b><button @click="handleBus">傳遞數值給須要的組件</button>
</div>
</template>
<script>
import Bus from './bus.js'
export default {
methods: {
handleBus () {
Bus.$emit('someBusMessage','來自ComponentA的數據')
}
}
}
</script>
複製代碼
// ComponentB.vue
<template>
<div>
<b>組件B:</b><button @click="handleBus">接收組件A的信息</button>
<p>{{message}}</p>
</div>
</template>
<script>
import Bus from './bus.js'
export default {
data() {
return {
message: ''
}
},
created () {
let that = this // 保存當前對象的做用域this
Bus.$on('someBusMessage',function (data) {
that.message = data
})
},
beforeDestroy () {
// 手動銷燬 $on 事件,防止屢次觸發
Bus.$off('someBusMessage', this.someBusMessage)
}
}
</script>
複製代碼
中央總線優勢:能夠解耦組件,方便兄弟間通訊
$parent
/ $children
& $refs
$parent
/ $children
:指定已建立的實例,在二者之間創建父子關係。子實例能夠用 this.$parent
訪問父實例,子實例被推入父實例的 $children
中。
$refs
:一個對象,持有註冊過 ref
特性的全部 DOM 元素和組件實例。ref
被用來給元素或子組件註冊引用信息。引用信息將會註冊在父組件的 $refs 對象上。
若是在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;若是用在子組件上,引用就指向組件。
父組件
<template>
<div id="app">
<!-- 前者自定義名稱便於子組件調用,後者要傳遞數據名 -->
<p>{{msg}}</p>
<child-one ref="childOne"></child-one>
<child-two ref="childTwo"></child-two>
<button @click="oneContent">顯示child-one傳過來的數據</button>
<button @click="twoOneContent">顯示hild-two傳過來的數據</button>
</div>
</template>
<script>
// 引入子組件
import ChildOne from './components/ChildOne'
import ChildTwo from './components/ChildTwo'
export default {
name: 'app',
components: {
ChildOne,
ChildTwo
},
data () {
return {
msg: '我是父組件',
content: 'James' //子組件要用的數據
}
},
methods: {
// button 的事件響應
oneContent () {
const childOne = this.$refs.childOne;
this.msg = childOne.msg;
},
twoOneContent () {
// 經過$refs取到childTwo
const childTwo = this.$refs.childTwo;
this.msg = childTwo.msg;
}
},
}
</script>
複製代碼
子組件1
<template>
<div>
<p>{{title}} 個人父組件是{{content}}</p>
</div>
</template>
<script>
//import x from ''
export default {
components: {
},
data () {
return {
content: '',
title: '我是子組件 childOne',
msg: '我只子組件childOne hello ereryOne'
};
},
mounted () {
// 從父組件裏取contet的數據
this.content = this.$parent.content;
},
}
</script>
複製代碼
子組件2:
<template>
<div>
<p>{{title}} 個人父組件是{{content}}</p>
</div>
</template>
<script>
//import x from ''
export default {
data () {
return {
content: '',
title: '我是子組件 childTwo',
msg: '我是子組件childTwo hello ereryOne'
};
},
mounted () {
// 加載父組件content的內容
this.content = this.$parent.content;
},
}
</script>
複製代碼
npm i pubsub --save
的方式引入pubsub庫event-type.js
定義Symbol類型的數據並導出// event-types.js
export const MY_TOPIC = Symbol('MY_TOPIC')
複製代碼
pubsub
和 event=type.js
,而且經過如下方式發佈事件import PubSub from 'pubsub'
import { MY_TOPIC } from './event-types.js'
PubSub.publish(MY_TOPIC, 'world');
複製代碼
pubsub
和 event=type.js
,而且經過如下方式接受事件import PubSub from 'pubsub'
import { MY_TOPIC } from './event-types.js'
PubSub.subscribe(MY_TOPIC, function (msg, data) {
console.log(data)
});
複製代碼
Vuex 是Vue官方推薦的一種解決組件中通訊的完美解決方案,也是在項目開發中必用的方案:
認真看完本篇後對照思惟導圖能夠在腦海裏回顧一遍哦,對此塊的知識點你會有更深的認識和理解.
若是個人分享對面前的這位大俠有所啓發,請不要吝嗇手中大拇指,以程序員最高禮遇點贊✨ 評論加分享的方式鼓勵我持續分享,也歡迎各位大佬勘誤,提出寶貴意見.
關注公衆號回覆:學習 領取前端最新最全學習資料,也能夠進羣和大佬一塊兒學習交流