[Vue] vue 元件傳值
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(); }); ...
在最初的專案階段這是一個不錯的選擇,但是隨著專案體積的增大,事件觸發和資料流向變得越來越不可見,後續開發和維護變得越來越困難.
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(() => { // ... })
其他的傳值還有一些傳統的方式
比如 localStorage,sessionStorage,router 傳參,cookie(不推薦,雖然就跟之前做購物
車差不多的傳遞形式)
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" } });