Vue2.0 多種元件傳值方法-不過如此的 Vuex
阿新 • • 發佈:2021-02-16
### 碼文不易啊,轉載請帶上本文連結呀,感謝感謝 https://www.cnblogs.com/echoyya/p/14404397.html
在vue專案中瞭解元件間通訊很重要,也是最基礎的面試題,可以大致總結為以下幾種情況和方法:
### 一、父向子傳值
`父 to 子` :通過`動態繫結屬性`的方式,子元件在`props`中去接收,佔為已用
```
// father.vue
data() {
return {
name:'Echoyya',
}
}
```
```
// child.vue
export default {
props: ['name'],
mounted() {
console.log(this.name) // Echoyya
}
}
```
### 二、子向父傳值 - 1. 事件分發 emit
`子 to 父` :通過`.emit('事件名稱', 傳遞的引數)事件分發`的方式, 父元件當中,呼叫子元件標籤上繫結自定義事件,其中包含一個`引數`,即子元件傳遞過來的資料
1. emit 只能接受兩個引數,其餘不生效,第一個引數:事件名稱,第二個: 傳遞的資料
2. 事件分發,不一定要通過點選事件,也可使用鉤子函式等
3. 需要傳遞多個引數時,emit第二個引數可選擇陣列或是物件
```
// father.vue
methods: {
getChildData(data){
console.log('子元件傳遞過來的資料:' + data);
}
}
```
```
// child.vue
export default {
data() {
return {
year:2021
};
},
methods:{
send(){
this.$emit('send',this.year)
}
}
};
```
### 三、子向父傳值 - 2. 父元件動態繫結方法
1. 除了平時常見的emit 事件分發的方式實現子向父傳值,還有一種不太常見的方式
2. 在前面有提到過,父向子傳值可以通過在標籤上動態繫結屬性的方式,同樣也可以`動態繫結方法`,在子元件`props`中接收
3. 在根據實際情況,在子元件中呼叫該方法,並傳值,此時父元件執行對應的方法及引數的處理,該引數便是子向父傳遞的資料
```
// father.vue
methods: {
getChildData(data){ // 子元件傳遞過來的資料
console.log(data); // 子元件 - 2021
}
}
```
```
// child.vue
export default {
props: ['fn'],
mounted(){
this.fn('子元件 - 2021')
}
};
```
### 四、(主動)父元件主動獲取子元件的資料和方法
1. 父元件中呼叫子元件,繫結一個`ref`屬性
2. 主動獲取屬性:`this.$refs.ref名稱.屬性`
3. 主動呼叫方法:`this.$refs.ref名稱.方法()`
```
// father.vue
mounted() {
console.log(this.$refs.child.year); // 2021
this.$refs.child.showName() // Echoyya:2021
}
```
```
// child.vue
export default {
data(){
return {
year:2021
}
},
methods:{
showName(){
console.log('Echoyya:'+ this.year);
}
}
};
```
### 五、(主動)子元件主動獲取父元件的資料和方法
1. 子元件中呼叫父元件,使用 `this.$parent`
2. 主動獲取屬性:`this.$parent.屬性`
3. 主動呼叫方法:`this.$parent.方法()`,還可以向父元件傳遞引數
```
// father.vue
```
```
// child.vue
export default {
mounted(){
console.log(this.$parent.name); // Echoyya
this.$parent.parentMethod(2021); // 2021
}
};
```
### 六、EventBus 傳值
多層級元件之間相互傳值,或兄弟元件之間傳值,通常使用`EventBus`,實際上就是 vm,即 Vue 的例項,通過釋出訂閱者模式,實現任意兩元件之間的通訊,父子亦可。
1. 首先建立EventBus檔案,匯出vm 例項
2. 在需要通訊的兩元件中分別引入該檔案
3. 通過釋出訂閱 `.$emit` 和 `.$on` 實現傳值 ,操作的事件名需相同。
```
// EventBus.js
import Vue from 'vue'
var vm = new Vue()
export default vm
```
```
// App.vue
```
```
// bus1.vue
元件 1 釋出
```
```
// bus2.vue
元件 2 訂閱
```
### EventBus 內部實現原理
1. 手動模擬一個 EventBus,實現釋出訂閱的效果,建立一個 myEventBus 檔案
2. 建立一個物件,分別設定釋出、訂閱的事件,以及事件儲存的物件,通過事件訂閱將事件儲存至事件物件中,
3. 事件釋出時,自動呼叫事件物件中相同 key 的所有事件
==**myEventBus.html**==
```
```
![](http://img2020.cnblogs.com/blog/1238759/202102/1238759-20210215161012147-1954564095.jpg)
### 七、不過如此的 Vuex
1. Vuex 應用程式開發的 **狀態管理模式**,集中式管理應用所有元件的狀態,進行元件通訊
2. 安裝外掛,引入 Vuex,建立 store 例項,配置到 Vue 例項中
3. 為防止狀態,方法宣告等過分重複和冗餘,Vuex 提供了一些輔助函式,`mapState`,`mapGetters`,`mapMutations`,`mapActions`,可使用擴充套件運算子展開,其中:
- `mapState`,`mapGetters`宣告在 computed 中
- `mapMutations`,`mapActions` 宣告在 methods 中
4. 建立 store 例項,核心屬性:
- `State`:一個物件,包含全部的應用狀態。作為`唯一資料來源`存在。store例項會注入到根元件下的所有子元件
- `Getters`:state 中資料派生出一些狀態類似計算屬性,返回值會根據它的依賴被快取起來,只有依賴發生改變時才會被重新計算,state 作為其第一個引數.
- `Mutations`:更改 store 中的狀態,`store.commit('事件名',payload引數可選)`觸發,只做同步操作,
- `Actions`:類似於Mutations, 提交的是 mutation,而不是直接變更狀態,可以包含任意非同步操作。`this.$store.dispatch`分發,非同步執行完畢,返回封裝的promise 物件。接受一個與 store 例項具有相同方法和屬性的物件
- `Modules`:為防止 store 物件過於複雜,可將其分割成模組,每個模組都有自己的State,Getters,Mutations,Actions,甚至可以巢狀子模組
![](http://img2020.cnblogs.com/blog/1238759/202102/1238759-20210215193913885-1557467617.gif)
```
// main.js
import Vue from 'vue'
import App from './App.vue'
import Vuex from 'vuex'
import numModule from './numModule.js'
Vue.use(Vuex)
var store = new Vuex.Store({
modules:{
numModule
}
})
new Vue({
store,
render: h => h(App)
}).$mount('#app')
```
```
// numModule.js
export default {
state: {
num: 1
},
getters: {
getNum(state) { // 可以返回一些派生狀態
return state.num
}
},
mutations: {
// 同步修改狀態的函式
changeNum(state, payload) {
state.num += payload.num
},
// 非同步時,開發工具會遺漏快照,不便於除錯(不推薦)
testAsync(state, data) {
// 模擬伺服器獲取資料
setTimeout(function () {
state.num += data
}, 0)
}
},
actions: {
// 非同步獲取資料,提交給 mutation 進行修改
incNumByService(store) {
setTimeout(function () {
var serviceData = 0.1
store.commit('changeNum', {
num: serviceData
})
}, 0)
}
}
}
```
```
// App.vue
第一元件
```
```
// Son.vue
第二元件
state:{{$store.state.numModule.num}}
getters:{{$store.getters.getNum}}
MapGetters:{{gn}}