如果你在項目中使用了 vuex模塊化,並且在項目中使用actions中函數調用頻率高,推薦瞭解一下這種方式。 比如下麵兩種方式調用 , 第一個是直接傳參設置, 第二個是添加了非同步ajax返回內容 在回調到等下我們要封裝的js中的成功回調里,然後這個成功回調就會反饋給組件 1.創建文件utils/vu ...
如果你在項目中使用了 vuex模塊化,並且在項目中使用actions中函數調用頻率高,推薦瞭解一下這種方式。
比如下麵兩種方式調用 ,
第一個是直接傳參設置,
第二個是添加了非同步ajax返回內容 在回調到等下我們要封裝的js中的成功回調里,然後這個成功回調就會反饋給組件
1.創建文件utils/vueTool.js
import storage from '@/utils/storage.js'; import store from '@/store/index.js'; const { dispatch, state } = store; /** * @vuexFunc 調用vuex模塊中的 Actions 並非同步回調結果 * @param modules {string} 調用指定的子模塊 如果是全局的可以不傳 * @param funcName {string} 調用Actions 函數名稱 * @param data {object} * @param followUp {string / object} * { data:{}, followUp:string / object function(res){} }, * data:當前調用介面需要的參數, * followUp 當前介面完成回調後 繼續執行更新介面的 名稱和參數 可以是請求地址字元串 可以是對象攜帶參數 * followUp:'URL' / followUp:{url:'請求介面地址',query:{參數}} * function回調函數 */ export function vuexFunc(modules = '', funcName = '', data = {}) { function send(followUp = '', query = null, lock = null) { // 消費憑證 if (typeof lock === 'number') { console.log('已消費:', lock) lock = true }; let url = ''; if (followUp) { url = followUp; } else { if (!modules && typeof modules !== 'boolean') { console.error('Actions函數名稱是必填。'); return; }; url = `${modules?modules+'/':''}${funcName}`; }; // 開發中使用 校驗當前調用的vuex模塊是否存在 if (process.env.NODE_ENV === 'development') { let modulesName = followUp ? followUp.split('/')[0] : typeof modules === 'boolean' ? funcName :modules; if (storage.getItem('modulesKey').indexOf(modulesName) === -1) { console.error(`找不到 ${modulesName} 請檢查!`); return; }; }; let queryData = {} if(typeof modules === 'boolean'){ queryData = data } else { queryData = followUp ? query ? query : {} :data.data && Object.keys(data.data).length?data.data:{} } dispatch(url, { // data: followUp ? query ? query : {} : data.data, data: queryData, callback(res) { // 成功 if (res !== 'failed') { if (lock) { console.log('停止了') return }; if (data.callback) { data.callback(res); }; if (data.followUp && typeof data.followUp === 'string') { console.log('開始後續回調') send(data.followUp, null, Date.now()); } else if (data.followUp && Object.keys(data.followUp).length) { if (!data.followUp.url) { console.error('缺少後續請求的url'); return; }; if (!data.followUp.hasOwnProperty('query')) { console.error('query欄位 缺少後續請求的參數,沒有參數直接傳入 string Url 形參'); return; }; send(data.followUp.url, data.followUp.query, Date.now()) }; // 失敗 -1 } else if (res === 'failed') { if (data.failed) { data.failed(res) } else { console.error('介面請求失敗:'+url) } }; } }); }; send(); } /** * @getState 獲取vuex中state倉庫 * @param modules {string} 倉庫名稱 如果是子模塊就傳入子模塊的名稱 */ export function getState(modules = '') { if (!modules) { console.error('state倉庫名稱是必填。'); return; }; return state[modules] }
2.添加開發環境中的模塊驗證
註意:如果你的vue3項目是使用webpack5創建的 那麼這裡的自動化導入文件 就不能使用,可以去看看我上篇文章中有寫webpack5如何自動化導入模塊
import { createStore } from 'vuex' import actions from './actions' import mutations from './mutations' import storage from '@/utils/storage.js' const modulesFiles = import.meta.glob('./modules/*/index.js', { eager: true }); const modules = Object.keys(modulesFiles).reduce( (modules, path) => { const moduleName = path.replace(/^\.\/(.*)\.\w+$/, '$1') modules[moduleName.split('/')[1]] = modulesFiles[path]?.default return modules }, {} ); let modulesKey = ''; if(process.env.NODE_ENV === 'development'){ let obj = {...actions,...modules}; for(let key in obj){ modulesKey+=key+',' }; storage.setItem('modulesKey',modulesKey); }; const store = createStore({ modules, state: { name: 'allen', modulesKey:storage.getItem('modulesKey') || modulesKey, }, mutations, actions, getters: {} }) export default store
3.頁面調用封裝
actions函數的調用
import { vuexFunc, getState } from '@/utils/vueTool'; vuexFunc('子模塊文件昵稱','actions.js中定義的函數昵稱',{ data:{介面需要的參數,或者你要設置到倉庫的值}, callback(res){ // 請求回調 console.log(res) } }); //模式一(調用全局actions函數) vuexFunc(false,'setStageCourse',{ data:query, callback(res){ console.log(res) } }); //模式二(調用子模塊函數中的actions函數) vuexFunc('index','setStageCourse',{ data:query, callback(res){ console.log(res) } }); // 模式三(調用完一個actions函數後立即執行另外一個actions函數) 這裡調用完成signIn子模塊中的loginByCode函數完成回調後,會立即去讀取followUp的配置
也是對應了 子模塊/signIn函數昵稱去執行,followUp允許一個具體的函數路徑或者一個對象可以配置函數要設置的值
vuexFunc('signIn','loginByCode',{ data:{code:wxcode.value}, followUp:'index/getConfig', callback(res){ SignType.value = false storage.setItem('authorization',res.data.token); } });
state倉庫的使用
import {vuexFunc,getState} from '@/utils/vueTool' // 獲取全局state let data = getState('全局state對象中定義的對象key')
// 獲取子模塊中的 state // getState('子模塊昵稱') 獲取到某個子模塊中的state倉庫對象 let data = getState('signIn').SigninType
最後:
這樣既擴展了功能 也不需要原本的vuex 先導入 在解構 在調用,並且對actions的控制和錯誤也做到了顆粒化捕獲,與攔截反饋,在一定程度上提高了開發過程中的程式調試。
後來我又思考了一下感覺還能繼續優化,比如像vue2中使用 ...mapActions 和 ...mapState 直接返回多個函數對象,感覺這樣會比較優雅,但是在項目中我已經開發過半了 所以就沒有對這個進行重新改造,有興趣的可以試試。