vue是一種mvvm框架杯缺,它相對于jquery可能比較大的差異點之一就在于組件之間的通信了。這里提供三種不同情況下vue組件的通信方式匿醒。
一. vue父子組件通信
vue父子組件通信可以用Vue.$emit自定義事件來解決场航。
// 父組件
<single-address @edit-address="editAddress"></single-address>
// 子組件
methods: {
editAddress () {
this.$emit('edit-address', false)
}
}
當然也可以使用props方式解決。
// 父組件
<one-address :addressitems="addressitems"></one-address>
// 子組件
<div>{{ addressitems.partment }}{{ addressitems.address }}</div>
export default {
props: {
addressitems: Object
}
}
二. 非父子組件通信
非父子組件通信同樣也可以用Vue.$emit自定義事件來解決
var bus = new Vue()
// 組件A
bus.$emit('id-selected', 1)
// 組件B
bus.$on('id-selected', function (id) {
console.log(id)
})
三. vue跨組件跨模塊通信
雖然父子組件廉羔,非父子組件間的通信vue都可以有辦法解決溉痢,但是如果項目結(jié)構(gòu)復雜化以后,這樣的自定義事件變多以后代碼難以管理,所以還是建議使用vuex孩饼。
接下來就講一講vuex這個東西吧髓削。vuex,官方的說法就是Vuex 是一個專為 Vue.js 應用程序開發(fā)的狀態(tài)管理模式镀娶。如果之前沒有接觸過應用狀態(tài)管理這一塊的內(nèi)容的話立膛,可能光看文檔是很難看明白的。按個人的理解來說梯码,vuex最大的作用就是把部分父子組件之間頻繁的通信過程簡單化宝泵,所以,對于一些父子組件通信并不頻繁的情況來說轩娶,并不應該使用vuex儿奶,當然這也意味著,如果你對父子組件之間的通信還不是很明確的話鳄抒,可以先學習一下這一塊的知識闯捎。
vuex有四個核心概念,其中state和getters主要是用于數(shù)據(jù)的存儲與輸出嘁酿,而mutations和actions是用于提交事件并修改state中的數(shù)據(jù)隙券。
也是以購物車的業(yè)務來舉例男应,首先由于vue的限制闹司,頁面中所有的數(shù)據(jù)都需要一個初始化,這樣才能在之后業(yè)務邏輯中響應式地修改數(shù)據(jù)(修改數(shù)據(jù)的同時變化頁面內(nèi)容)沐飘。這里我們可以在vue組件中使用ajax獲取數(shù)據(jù)游桩,獲取到的數(shù)據(jù)直接賦給state中的數(shù)據(jù):
// global.Domain.centerUrl是我自己定義的全局變量,這種就可以更方便的管理前端數(shù)據(jù)請求接口的地址了
getDataFromBackend () {
this.$http({
method: 'get',
url: global.Domain.centerUrl + 'order'
}).then(function (response) {
let res = response.data
// state.order是因為我對整個應用進行了分模塊的設(shè)計耐朴,order是我其中的一個模塊借卧,后面會講如何劃分模塊
// $store是vue實例的全局屬性,這個屬性可以直接獲取vuex狀態(tài)樹中的所有state數(shù)據(jù)
this.$store.state.order.orderitems = res.orderitems
})
}
getters的用法與計算屬性基本一致筛峭,computed會用的話那這個也基本就會用了铐刘。
接下來就是重頭戲mutations了。mutations原意是突變影晓,這里可以理解為立即修改吧镰吵。也就是說,mutations可以修改state中的數(shù)據(jù)挂签,但是有一個限制疤祭,那就是只能同步修改,而不能異步饵婆,你想要按個定時器過2秒鐘修改state勺馆,那對不起了您哪,不行。但是草穆,想要異步修改state灌灾,也不是不行,光靠mutations一個人是不行的了悲柱,還得要靠actions紧卒,而且actions還不能直接操作state,他需要異步提交給mutations诗祸,然后再由mutations同步修改state數(shù)據(jù)跑芳。聽上去挺麻煩的一件事情啊,還是直接看代碼吧直颅。
mutations: {
correctIfcollect (state) {
state.ifcollectwrap = true
},
modifyIfcollect (state) {
state.ifcollectwrap = false
},
// 收藏成功事件
collectSuccess (state) {
state.ifcollect = true
state.collectmsg = '收藏成功'
},
// 取消收藏事件
collectCancel (state) {
state.ifcollect = false
state.collectmsg = '取消收藏'
}
},
actions: {
// actions有一個必要的參數(shù)commit博个,用于提交事件到mutations中
collectPopup ({commit, state}) {
let oTimer = ''
clearTimeout(oTimer)
if (!state.ifcollect) {
commit('collectSuccess')
commit('correctIfcollect')
oTimer = setTimeout(function () {
commit('modifyIfcollect')
}, 2000)
} else {
commit('collectCancel')
commit('correctIfcollect')
oTimer = setTimeout(function () {
commit('modifyIfcollect')
}, 2000)
}
}
}
// 假如有數(shù)據(jù)需要從組件傳到actions中時,需要兩個大括號功偿,第一個大括號放commit或者state這類vuex參數(shù)盆佣,而第二個大括號放傳進來的參數(shù)
// 這里使用vuex actions調(diào)用了兩個mutations的方法實現(xiàn)一個功能,是因為第二個函數(shù)中有一個參數(shù)是需要第一個函數(shù)提供的
changePos ({commit}, {index}) {
commit('changeHandle', index)
commit('changePos', index)
}
總的來說械荷,在我看懂了vuex以后共耍,我總是覺得有一個vuex來分擔一下data的功能那是再好不過了,這樣不光能夠更好地管理我的應用吨瞎,同時也能夠提高我.vue單文件的可讀性痹兜。
那么這里就有一個問題了,我們都知道一個稍微大一點的項目颤诀,那數(shù)據(jù)量都是很多的字旭,如果整個項目里的數(shù)據(jù)都寫在一個vuex文件里的話就顯得整個文件太大太重了,這與我們想要提高文件的可讀性是相悖的崖叫。所以我們需要有一個分模塊的意識來管理vuex遗淳,管理應用的狀態(tài)。
而vuex也正好提供了這個功能(vuex還真的是夠強大)心傀,在具體使用的過程中屈暗,我會先把那些需要與其他組件交互的組件中的數(shù)據(jù)都提取出來放到vuex里面管理,而那些完全沒有交互的數(shù)據(jù)還是放在組件的data中脂男,例如標識該組件的標題數(shù)據(jù)等等养叛。然后,這里我們就可以用到vuex的模塊管理功能疆液,愉快地把數(shù)據(jù)按照組件之間的功能聯(lián)系來分離一铅,并把它們拆分到一個個小文件中啦。
// 這是vuex總的管理文件堕油,將各模塊統(tǒng)一在一起潘飘,從而將每一個分支都連接到vuex這個總的狀態(tài)樹上
// 引入vue
import Vue from 'vue'
// 引入vuex
import Vuex from 'vuex'
// 引入應用狀態(tài)管理
import goodshandleStore from './goodshandle'
import orderStore from './order'
import addressStore from './address'
import shopcarStore from './shopcar'
import merchantStore from './merchant'
import couponStore from './coupon'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
handle: goodshandleStore,
order: orderStore,
address: addressStore,
shopcar: shopcarStore,
merchant: merchantStore,
coupon: couponStore
}
})