[Vue] vuex進行組件間通訊

vue 組件之間數據傳輸(vuex)

初始化 store

src/main.js

import Vuex from "vuex";
Vue.use(Vuex);

new Vue({
  ...,
  store,
  ...,
});

src/store/index.js

import mutations from "./mutations";

const initStore = {
  state: {
    userBasicInfo: {},
    siteBaseInfo: {
      download: "",
      invitation: "",
      register_enable: "",
      service_qq1: "",
      service_qq2: "",
      service_wechat: "",
    },
  },
  mutations
};

export default initStore;

src/store/mutations.js

const SET_USER_BASIC_INFO = 'SET_USER_BASIC_INFO';
const SET_SITE_BASE_INFO = 'SET_SITE_BASE_INFO';

export default {
  [SET_USER_BASIC_INFO](state, payload) {
    state.userBasicInfo = payload.data;
  },
  [SET_SITE_BASE_INFO](state, payload) {
    state.siteBaseInfo = Object.assign({}, state.siteBaseInfo, payload);
  },
}

state

正常使用 state

Vuex 的狀態存儲是響應式的,從 store 實例中讀取狀態最簡單的方法就是在計算屬性中返回某個狀態。每當 store.state.count 變化的時候, 都會重新求取計算屬性,並且觸發更新相關聯的 DOM。 Vuex 通過 store 選項,提供了一種機制將狀態從根組件“注入”到每一個子組件中。

const app = new Vue({
  el: '#app',
  // 把 store 對象提供給 “store” 選項,這可以把 store 的實例注入所有的子組件
  store,
  components: { Counter },
  template: `
    <div class="app">
      <counter></counter>
    </div>
  `
})

在子組件中使用

const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}

mapState 輔助函數

按官網的案例

import { mapState } from 'vuex'

export default {
  // ...
  computed: mapState({
    // 箭頭函數
    siteBaseInfo: state => state.siteBaseInfo,
    // 傳字符串參數
    siteBaseInfo: "siteBaseInfo",
    // 爲了能夠使用 `this` 獲取局部狀態,必須使用常規函數
    download_ios (state) {
      return state.siteBaseInfo.download + this.prefix
    },
    download: state => state.siteBaseInfo.download
  })
}

當映射的計算屬性的名稱與 state 的子節點名稱相同時,我們也可以給 mapState 傳一個字符串數組

computed: mapState([
  // 映射 this.count 爲 store.state.count
  'count'
])

mapState 與局部計算屬性混合使用

使用對象展開運算符將多個對象合併爲一個,以使我們可以將最終對象傳給 computed 屬性。

computed: {
  localComputed () { /* ... */ },
  // 使用對象展開運算符將此對象混入到外部對象中
  ...mapState({
    // ...
  })
}

getter 的使用

有時候我們需要從通過 state 得到一些新的狀態,因爲這一狀態可能其他很多組件都要使用這一狀態.比如餘額這一參數,我們當前只有盈利和虧損額,但是很多頁面都要使用餘額進行顯示,那麼每個引入頁面都要進行一次計算嗎?想想就麻煩,還是隻計算一次,然後直接獲取這個餘額值來的方便

store/getters.js

export default {
  balance: (state) => {
    return Number(state.userBasicInfo.profit) - Number(state.userBasicInfo.loss);
  },
  download: (state) => {
    return state.siteBaseInfo.download;
  }
}

mapGetters 輔助函數

輔助函數僅僅是將 store 中的 getter 映射到局部計算屬性

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
  // 使用對象展開運算符將 getter 混入 computed 對象中
    ...mapGetters([
      'balance',
      'download',
      // ...
    ])
  }
}

getter 的使用

//直接使用
store.getters.download
//組件中使用
computed: {
 download () {
    return this.$store.getters.download
  }
}
//使用輔助函數
...mapGetters([
      'download',
      'balance',
])
//和mapState一起用
computed: {
  ...mapState({
    siteBaseInfo: "siteBaseInfo",
  }),
  ...mapGetters({
    download: 'download'
  })
},

Getter 也可以接受其他 getter 作爲第二個參數

getters: {
  // ...
  doneTodosCount: (state, getters) => {
    return getters.doneTodos.length
  }
}

總之,getter 就是一個將一些需要進行再次計算的 state 計算好,然後將其作爲 state 進行快捷的引用

mutation 使用

  • 最好提前在你的 store 中初始化好所有所需屬性
  • 當需要在對象上添加新屬性時,你應該使用 Vue.set(obj, 'newProp', 123)或以新對象替換老對象(對象展開符)
  • mutation 必須是同步函數

每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler),會接受 state 作爲第一個參數

//設置
mutations: {
   SET_USER_BASIC_INFO(state) {
    state.userBasicInfo = {a:1,b:2};
  },
}

//使用
store.commit('SET_USER_BASIC_INFO')

提交載荷(Payload)

//設置
mutations: {
   SET_USER_BASIC_INFO(state, payload) {
    state.userBasicInfo = Object.assign({},payload);
  },
}

//使用
store.commit('SET_USER_BASIC_INFO', {
  a:1,
  b:2
})

對象風格的提交方式

提交 mutation 的另一種方式是直接使用包含 type 屬性的對象

store.commit({
  type: 'SET_USER_BASIC_INFO',
  data:{
      a:1,
      b:2,
  }
})

//mutations的效果
mutations: {
  increment (state, payload) {
    state.userBasicInfo = Object.assign({},payload.data);
  }
}

使用常量替代 Mutation 事件類型

// mutation-types.js
export const SET_USER_BASIC_INFO = 'SET_USER_BASIC_INFO';

// mutations.js
import { SET_USER_BASIC_INFO } from './mutation-types';

mutations: {
    // 我們可以使用 ES2015 風格的計算屬性命名功能來使用一個常量作爲函數名
    [SET_USER_BASIC_INFO] (state) {
      // mutate state
    }
  }

mapMutations 輔助函數

//正常
this.$store.commit('SET_USER_BASIC_INFO');

//mapMutations
import { mapMutations } from 'vuex';

export default {
    ...,
    methods:{
        ...mapMutations({
            setUserBasicInfo: 'SET_USER_BASIC_INFO' // 將 `this.setUserBasicInfo()` 映射爲 `this.$store.commit('SET_USER_BASIC_INFO')`
        })
    }
}

action

用來提交一個 mutation,還可以進行異步操作

//註冊
const store = new Vuex.Store({
  state,
  mutations,
  actions: {
    //解構context.commmit
    GET_HOME_INFO({commit}) {
        commit("SET_USER_BASIC_INFO");
    },
  }
})

//觸發
store.dispatch('GET_HOME_INFO')
//載荷形式
store.dispatch('GET_HOME_INFO',{})
//對象形式
store.dispatch({
    type:'GET_HOME_INFO',
    data:{}
})

mapActions 輔助函數

import { mapActions } from 'vuex'

export default {
  ...
  methods: {
    ...mapActions({
      getHomeInfo: 'GET_HOME_INFO' // 將 `this.getHomeInfo()` 映射爲 `this.$store.dispatch('GET_HOME_INFO')`
    })
  }
}

異步的 action

action 中的中支持的異步 ajax,setTimeout,acync/await,promise...

store.dispatch('actionA').then(() => {
  // ...
})

其他的傳值還有一些方式

比如 props,seventBus,slocalStorage,sessionStorage,router 傳參,cookie(不推薦,雖然就跟之前做購物車差不多的傳遞形式)

vue 組件之間數據傳輸(props 傳值方式)

這個多用於父子組件之間的傳值,是最基本的傳值方式

父親組件進行綁定,將數據綁定,其中 personal,personalData,imgUrl 是綁定的數據,@updata 是綁定的事件

<template>
      ...
      <slideBar
        @updata="updata"
        :personal="personal"
        :personalData="personalData"
        :imgUrl="imgUrl"
      ></slideBar>
      ...
<template>

子組件進行獲取數據通過 props 進行獲取,可以設置一些靜態類型檢查,類似於 react 的 proptypes,同時子組件想要向父組件進行傳值,可以通過 emit 進行傳值就行了

  export default {
    props: {
      slideMsg: Array,
      personal: Object,
      personalData: Object,
      imgUrl: String
    },
    ...
    methods:{
      submitEvent(){
        ...
        this.emit("updata","我是獲取的數據");
        ...
      }
    }
  }

vue 組件之間數據傳輸(eventBus 進行組件傳遞)

事件 bus 通過一個新的 vue 實例,來進行事件監聽和事件分發 commom/bus.js

//極簡單的vue實例
import Vue from 'vue';
// 使用 Event Bus
const bus = new Vue();
export default bus;

在 game 組件中引入

import bus from "@/common/bus";

...
bus.$emit("moneyChange", {....});
...

在用 money 組件中引入

import bus from "@/common/bus";

...
bus.$on("moneyChange", msg => {
    msg && this.initHomeData();
});
...

在最初的項目階段這是一個不錯的選擇,但是隨着項目體積的增大,事件觸發和數據流向變得越來越不可見,後續開發和維護變得越來越困難.

sessionstorage

項目中使用的 sessionStorage

sessionStorage.setItem("msg", JSON.stringify(res.data)); //爲了兼容之前的代碼,有用到msg這個本地緩存的數據
sessionStorage.setItem("isMobile", res.data.mobile);
sessionStorage.setItem("invi", res.data.invitation);
sessionStorage.setItem("isLogin", res.data.trier);
sessionStorage.setItem("setPwd", res.data.fundpwd);
sessionStorage.setItem("isShow", res.data.bankcard);

localStorage

項目中關於聲音的開關,樣式選擇,背景切換等,用來將用戶的一些操作一直保存

//組件userSetting
localStorage.setItem("audio", this.switchValue);
//組件audioPlay
let audio = localStorage.getItem("audio");

sessionstorage 和 localStorage 看情況使用就好,sessionstorage 是瀏覽器關閉沒了,localStorage 是一直存儲不刪除就在存在

params

依賴於 vue-router

this.$router.push({
  name: "Main",
  params: {
    id: this.setting_id,
    type: "3"
  }
});

Vuex Vuex - 標籤 - 掘金 浪裏行舟 從頭開始學習 Vuex VueJS 中學習使用 Vuex 詳解 到底 vuex 是什麼? 基於 vue2 + vuex 構建一個具有 45 個頁面的大型單頁面應用

原文出處:https://www.cnblogs.com/mybilibili/p/10456346.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章