在vue2中,提供了provide和inject配置,可以讓開發者在高層組件中註入數據,然後在後代組件中使用 除了相容vue2的配置式註入,vue3在composition api 中添加了provide和inject方法,可以在setup函數中註入 和使用數據 基本使用 provide('key' ...
在vue2中,提供了provide和inject配置,可以讓開發者在高層組件中註入數據,然後在後代組件中使用 除了相容vue2的配置式註入,vue3在composition api 中添加了provide和inject方法,可以在setup函數中註入 和使用數據 基本使用 provide('key',value)
// app.vue 定義數據 <script setup> import { provide,ref } from 'vue' const sum = ref(1) provide('foo',sum) </script>
// 其他頁面調用 <script setup> import { inject } from 'vue' let foo = inject('foo')//傳入key 在其他任意頁面都能獲取到 console.log(foo.value)// 1 </script>考慮到有些數據需要在整個vue應用中使用,vue還在應用實列中加入了provide方法,用於提供整個應用的共用數據
creaetApp(App).provide('fpp',ref(1)).provide('foo',ref(2)).mount('#app')因此,我們可以利用這一點,在整個vue應用中提供共用數據 目錄結構:
模塊封裝
userSever.js// 模擬ajax api介面使用 const userSery = { // 登錄介面 login: (name,age) =>{ // 介面返回用戶數據 儲存在本地 return new Promise((resolve,reject)=>{ setTimeout(()=>{ let user = { name :name, age:age } window.sessionStorage.setItem('user',JSON.stringify(user)) console.log('登錄成功') resolve(user) },1000) }) }, // 退出登錄 loginOut:()=>{ return new Promise((resolve,reject)=>{ setTimeout(()=>{ window.sessionStorage.removeItem('user') resolve('退出成功') },1000) }) }, // 恢復登錄 whoAmI:()=>{ // 讀取本地儲存的用戶數據 return new Promise((resolve,reject)=>{ setTimeout(()=>{ let user = window.sessionStorage.getItem('user'); if(user){ user = JSON.parse(user); console.log('恢覆成功',user) resolve(user); } else { reject('恢復失敗'); }; },1000) }) } } // store 提供當前登錄用戶的共用數據 import { readonly,reactive,inject } from 'vue'; const key = Symbol(); // 在傳入的vue應用實列中提供數據 export function provideStore(app){ // 創建預設的響應式數據 const state = reactive({user:null,loading:false}); // 登錄 async function login (loginId,loginPwd){ state.loading = true const user = await userSery.login(loginId,loginPwd); state.user = user; state.loading = false } // 退出 async function loginOut (){ state.loading = true await userSery.loginOut(); state.user = null; state.loading = false } // 恢復登錄狀態 async function whoAmI (){ state.loading = true try { const user = await userSery.whoAmI(); state.user = user; state.loading = false } catch (e) { state.user = null; } state.loading = false } app.provide(key,{ state:readonly(state), // 對外只讀 login, loginOut, whoAmI }) } export function useStore(defaultValue = null){ return inject(key,defaultValue) }View Code 封裝註入模塊給app src/store/index.js
import { provideStore as provideLoginUserStore } from "./userSever.js" // 繼續導入其他共用數據模塊... // import {provideStore as provideNewsStore } from './sueNew.js' // 提供統一的數據註入介面 export default function provideStore (app){ provideLoginUserStore(app); // 繼續註入其他共用數據 // provideNewsStore }main.js導入並且註入app
import { createApp } from 'vue' import App from './App.vue' import router from './router' import provideStore from './store' const app = createApp(App).use(router); provideStore(app) // 提供所有共用數據 app.mount('#app') // createApp(App).use(store).use(router).mount('#app')到這裡就已經完成了 全部準備工作 在你想調用的地方和頁面進行下麵引入和使用
import { useStore} from '../store/userSever.js' const Store = useStore() console.log(Store.state); //定義的state響應式數據 // 下麵調用 導入模塊的指定的函數方法去修改 state共用的響應式數據內容 // 點擊 登錄 const loginEvent = ()=>{ Store.login('allen',18) }; // 退出登錄 const loginOutEvent = ()=>{ Store.loginOut() }; // 恢復登錄 Store.whoAmI()
共用響應式數據,在A頁面使用到了state,在B頁面去調用函數改變 state 那麼A頁面的state數據也會發送改變,只要使用到的 state的地方都會響應式改變數據,相比vuex 更加輕量級 更加具有自定義擴展的能力,因為他本身不依賴任何第三方插件,完全是靠 vue本身提供的獨立響應式系統來實現的。