1. 程式人生 > >Vue2.0 多種元件傳值方法-不過如此的 Vuex

Vue2.0 多種元件傳值方法-不過如此的 Vuex

### 碼文不易啊,轉載請帶上本文連結呀,感謝感謝 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 ``` ``` // bus2.vue ``` ### 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