1. Vuex
1.1 安装vuex
npm install vuex@latest
1.2 创建store文件夹,创建index.js文件
在vuex@4.x中 创建vuex实例需要使用createStore方法
// store/index.js
import { createStore } from 'vuex'
import useLoginStore from './modules/login'
export default createStore({
modules: {
useLoginStore
}
})
1.3 创建store/modules文件夹,创建login.js文件
在这里遇到了一个问题,就是需要使用createStore方法创建store实例,这样在应用模块的情况下是不生效的。如果在应用模块的情况下需要导出一个普通对象。如下:
问题解决参考:
// 问题解决参考:https://github.com/vuejs/vuex/blob/main/examples/composition/shopping-cart/store/modules/products.js
export default {
namespaced: true,
state:{
....
},
mutations:{
...
},
actions:{
....
},
getters:{
....
}
}
1.5 挂载到vue应用上
createApp().use(store).mount('#app')
1.6 开始应用
注意:在vue3中,由于没有了this,所以需要使用引入useStore方法,来获取store实例。
import { useStore } from 'vuex'
setup(){
const store = useStore();
// 获取state
store.state.useLoginStore.xxx
// 异步请求
store.dispatch('useLoginStore/xxx')
// 同步状态
store.commit('useLoginStore/xxx')
// 获取getters OR 也可以通过:computed(()=> store.state.useLoginStore.xxx)
store.getters['useLoginStore/xxx']
}
2. Global State
在vue3中,组件和响应式功能被隔离开了,也就是说在任意一个JavaScript文件中都可以使用响应式功能。不同vue2组件与响应式耦合在一起。那么可以借助这个特性创建全局状态
2.1 创建store文件夹,创建useLoginStore.js文件
// useLoginStore.js
const state = reactive({
....
})
const store = readonly(state);// 只读
function Login(){
...
}
function logout(){
...
}
export {
store,
Login,
logout,
...
}
3. Provide / Inject
在vue2
中,提供了provide
和inject
配置,可以让开发者在高层组件中注入数据,然后在后代组件中使用
除了兼容vue2
的配置式注入,vue3
在composition api
中添加了provide
和inject
方法,可以在setup
函数中注入和使用数据
考虑到有些数据需要在整个vue应用中使用,vue3
还在应用实例中加入了provide
方法,用于提供整个应用的共享数据
3.1 提供整个应用响应式对象,可以被后代组件使用
// useLoginStore.js
function provideLoginStore(app){
const state = reactive({})
function Login(){
}
function logout(){
}
app.use(key,{
state,
Login,
logout,
})
}
function useLoginStore(defalutValue = null){
return inject(key, defalsutValue)
}
export {
provideLoginStore,
useLoginStore
}
3.2 进一步封装
未来可能会有很多个store,将useLoginStore抽离出去,直接维护这个index.js文件,然后main.js也只调用这个
// index.js
import { provideLoginStore } from './useLoginStore'
// 继续导入其他共享数据模块...
// import { provideStore as provideNewsStore } from "./useNews"s
// 提供统一的数据注入接口
function installStores(app){
app.use(provideLoginStore);
// 继续注入其他共享数据
// provideNewsStore(app);
}
3.3 注册到全局
const app = createApp(App);
installStores(app);// 这样就把所有的store都注册到全局了
3.4 使用
// 子组件
import { injectStore } from './store/useLoginUser'
const store = injectStore();
对比
vuex | global state | Provide&Inject | |
---|---|---|---|
组件数据共享 | ✅ | ✅ | ✅ |
可否脱离组件 | ✅ | ✅ | ❌ |
调试工具 | ✅ | ❌ | ✅ |
状态树 | ✅ | 自行决定 | 自行决定 |
量级 | 重 | 轻 | 轻 |