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 個頁面的大型單頁面應用