在父組件中,能夠經過子組件標籤屬性的形式將數據或者函數傳給子組件,子組件經過props去讀取父組件傳過來的數據vue
用法vuex
父組件傳數據給子組件:bash
通常的屬性值都是用來給子組件展現的app
子組件傳數據給父組件異步
屬性值爲函數類型的,通常是用來子組件向父組件傳遞數據,子組件經過調用父組件傳過來的函數,能夠修改父組件的狀態數據函數
缺點:工具
隔層組件間傳遞: 必須逐層傳遞(麻煩)優化
兄弟組件間: 必須藉助父組件(麻煩)ui
注意:this
//子組件獲取父組件傳過來的值
props: {
obj: {//obj爲{id:'2'}
type: Object
}
}複製代碼
引用類型的props,咱們能夠在子組件中直接修改引用類型屬性的值(如:this.obj.id='3',會生效),可是不能直接改變引用類型存儲的地址值(如:this.obj = {id: '3'}),會發出警告。
雖然子組件能夠直接修改父組件的狀態值,但咱們不建議這樣作,咱們但願全部的 prop 都使得其父子 prop 之間造成了一個單向下行綁定:父級 prop 的更新會向下流動到子組件中,可是反過來則不行。這樣會防止從子組件意外改變父級組件的狀態,從而致使你的應用的數據流向難以理解。
髒數據問題:如v-model是實現了雙向綁定,經過v-model更改數據,會更改父組件的數據,致使髒數據
解決方法:
利用計算屬性的set和get,在set中需實現子組件調用父組件的方法,確保數據流向是單向的
computed:{
msg: {
get(){
return this.data
},
set(){
this.$emit('EventName', this.data)
}
}}複製代碼
方式1: 給子組件標籤綁定事件監聽
子組件向父組件的通訊方式
功能相似於function props
經過在父組件中給子組件標籤綁定自定義事件的監聽,再由子組件觸發事件,實現子組件向父組件傳遞數據的方法,事件名必須一致,且不能有大寫字母,v-on
事件監聽器在 DOM 模板中會被自動轉換爲全小寫 (由於 HTML 是大小寫不敏感的)
// 方式一: 經過v-on綁定
<component @delete_todo="deleteTodo"/>
// 方式二: 經過$on()綁定
this.$refs.xxx.$on('delete_todo', function (todo) {
this.deleteTodo(todo)})
經過this.$emit('delete_todo', todo)觸發事件複製代碼
不適合隔層組件和兄弟組件間的通訊
注意:
在組件標籤上綁定事件,會被解析爲vue自定義事件
在普通的標籤上綁定事件,會被解析爲DOM事件
<--!
表示在組件component綁定了一個名爲click的vue自定義事件,
至關於作了vm.$on('click',fn)
注意:不是常規理解的點擊事件,這裏與點擊無關,只是名字恰好是click,
固然實際操做中不建議取這類特殊的名字
-->
<component @click="fn"/>
<--! 表示在div上綁定一個click的點擊事件,是DOM事件 -->
<div @click="fn"/>複製代碼
方式2: 經過單獨的vm對象綁定監聽/分發事件
任意組件間通訊(相似於pubsub)
建立一個公用的vm對象
import Vue from 'vue'export default new Vue()複製代碼
在接收消息的組件,綁定監聽
import vm from './vm.js'mounted(){
vm.$on('delete_todo', function (todo) {
this.deleteTodo(todo)
})}複製代碼
在發送消息的組件,觸發事件
vm.$emit('delete_todo', todo)複製代碼
事件總線(EventBus),其實跟上面的用法同樣,這裏是把vm實例綁在了Vue的顯示原型上
//點擊任意一個組件,其餘組件的值跟着變化,利用總線去實現兄弟之間的通訊
Vue.prototype.bus = new Vue()
var vm = new Vue({
el:"#app"
})
//v-a組件
Vue.component('v-a', {
template:'<div @click="handle">{{msg}}</div>',
data(){
return {
msg: 'v-a'
}
},
mounted () {
//綁定事件監聽
this.bus.$on('bus',(msg)=>{
this.msg = msg
})
},
methods: {
handle () {
//觸發事件
this.bus.$emit('bus', this.msg)
}
}})
//v-b組件
Vue.component('v-b', {
template:'<div @click="handle">{{msg}}</div>',
data(){
return {
msg: 'v-b'
}
},
mounted () {
//綁定事件監聽
this.bus.$on('bus',(msg)=>{
this.msg = msg
})
},
methods: {
handle () {
//觸發事件
this.bus.$emit('bus', this.msg)
}
}})複製代碼
適用於任何關係的組件間的通訊
缺點:相對於vuex,管理不夠集中
用法:
引入pubsub-js庫
在接收消息的組件訂閱消息(subscribe)
PubSub.subscribe('name',(name,data)=>{})複製代碼
在發送消息的組件發佈消息 ( publish)
PubSub.publish('name',data)複製代碼
其餘用法能夠參考官方API文檔,這裏不細說
vuex是專門爲vue.js應用程序定義的狀態管理模式,當多個組件須要共享數據時,咱們通常用vuex去管理狀態數據,實現多個組件間的相互通訊
vuex的核心
state:存放數據
mutations:修改數據
actions:提交mutation,修改數據
getters:存放數據,相似於vue的計算屬性
知道了這幾個核心概念後,咱們還須要知道怎麼合理使用他們
如何從倉庫store讀取數據
state
從store的實例中咱們能夠經過store.state去得到狀態數據,爲了使得store能夠全局使用,咱們須要經過Vue.use(Vuex),將vuex注給全部vue子的組件,Vue.use回去調用插件的install方法,將stroe綁到Vue.prototype,這樣Vue的實例對象都能經過vm.store獲取或操做倉庫的數據組件內經過this.$store.state能夠得到
state:{
data: 0
}複製代碼
getters
有些狀態熟悉須要根據其餘狀態屬性計算而動態得到,通常都是存在getters中,組件經過調用this.$store.getters
Getter 接受 state 做爲其第一個參數
getters:{
data2(state){
return state.data+1
}
}複製代碼
如何修改倉庫store的數據
mutations(同步修改)
更改 Vuex 的 store 中的狀態的惟一方法是提交 mutation,接受 state 做爲第一個參數 ,mutation接收提交載荷,第二個參數爲載荷,在大多數狀況下,載荷應該是一個對象 ,這樣能夠接收多個數據
mutations:{
mutationType:(state,data)=>{
state.data = data
}
}複製代碼
actions(異步修改)
在action中提交mutation,組件經過store.dispatch觸發action
由於vue的調試工具沒法檢測到mutations的異步變化,因此咱們若是須要異步修改狀態數據,通常是放在action去異步獲取到數據後再提交mutation,確保vue的調試工具能夠檢測到,mutation的變化
注意點:
當組件須要給vue中的狀態數據添加屬性時,經過obj.的形式沒法實現
由於Vuex 的 store 中的狀態是響應式的,那麼當咱們變動狀態時,監視狀態的 Vue 組件也會自動更新。這也意味着 Vuex 中的 mutation 也須要與使用 Vue 同樣遵照一些注意事項:
咱們最好提早在 store 中初始化好全部所需屬性。
當須要在對象上添加新屬性時,咱們應該
使用 Vue.set(obj, 'newProp', 123)
, 或者
以新對象替換老對象。例如,利用 stage-3 的對象展開運算符,咱們能夠這樣寫:
state.obj = { ...state.obj, newProp: 123 }複製代碼
優化
import {mapState,mapGetters,mapMutations,mapActions} from "vuex";使得在使用vuex時,組件能夠寫的更加的簡潔
數據比較多的時候,使用module
使用常量存放mutation_type
優勢:
多組件共享狀態(數據的管理)
組件間的關係也沒有限制
功能比pubsub強大, 更適用於vue項目
父向子通訊
通訊是帶數據的標籤
注意: 標籤是在父組件中解析