Redux、Vuex、Pinia中的Store

46 阅读4分钟

一个react项目中可以有多少个redux中的store?/ 一个vuex中有多少个store?

通常在一个React项目中,只会有一个Redux store。设计Redux时的理念就是应用状态应该集中在一个单一的store中。

在 Vue.js 应用中,Vuex 通常也只会有一个 store,类似于 Redux 在 React 中的用法。Vuex 的设计理念也是集中式状态管理,将所有的应用状态集中在一个单一的 store 中。这种设计有助于保持应用的状态管理一致性和简洁性。

单一 Store 的优点:

  1. 单一数据源:所有的应用状态都存储在一个地方,便于管理和调试。
  2. 更容易实现时间旅行调试:由于状态集中在一个地方,可以更容易地实现时间旅行调试。
  3. 简化数据流:通过单一store,可以更容易地理解数据在应用中流动,从而减少复杂性。
  4. 工具支持

使用单一Store的典型模式:

Redux版:

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import rootReducer from './reducers';
import App from './App';

// 创建 Redux store
const store = createStore(rootReducer);

// 将 store 提供给应用
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

Vuex版:

import Vue from 'vue';
import Vuex from 'vuex';
import App from './App.vue';

Vue.use(Vuex);

// 定义 Vuex store
const store = new Vuex.Store({
  state: {
    // 应用状态
  },
  mutations: {
    // 状态突变
  },
  actions: {
    // 异步操作
  },
  getters: {
    // 计算属性
  }
});

// 创建 Vue 实例并提供 Vuex store
new Vue({
  store,
  render: h => h(App)
}).$mount('#app');

多个Store的问题

  1. 复杂性增加:多个store会增加应用的复杂性,使得数据管理和调试变得更加困难。
  2. 共享状态:多个store之间共享状态会变得更加困难,需要额外的逻辑来同步不同store之间的状态。
  3. 工具支持:大多数Redux工具和中间件都是单一store设计的,使用多个store可能会导致一些工具和中间件无法正常工作。

Redux版:

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import reducer1 from './reducer1';
import reducer2 from './reducer2';
import App from './App';
import SubComponent from './SubComponent';

// 创建两个 Redux store
const store1 = createStore(reducer1);
const store2 = createStore(reducer2);

ReactDOM.render(
  <Provider store={store1}>
    <App />
    <Provider store={store2}>
      <SubComponent />
    </Provider>
  </Provider>,
  document.getElementById('root')
);

Vuex版

import Vue from 'vue';
import Vuex from 'vuex';
import App from './App.vue';
import SubComponent from './SubComponent.vue';

Vue.use(Vuex);

// 创建两个 Vuex store
const store1 = new Vuex.Store({
  state: {
    // 应用状态1
  },
  mutations: {
    // 状态突变1
  },
  actions: {
    // 异步操作1
  },
  getters: {
    // 计算属性1
  }
});

const store2 = new Vuex.Store({
  state: {
    // 应用状态2
  },
  mutations: {
    // 状态突变2
  },
  actions: {
    // 异步操作2
  },
  getters: {
    // 计算属性2
  }
});

new Vue({
  store: store1,
  render: h => h(App)
}).$mount('#app');

// 在 SubComponent 中使用 store2
new Vue({
  store: store2,
  render: h => h(SubComponent)
}).$mount('#sub-component');

模块分割

1. Redux中模块分割

在Redux中通过模块化配置将状态分割成多个模块。

// counterReducer.js
const initialState = { count: 0 };

export function counterReducer(state = initialState, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { ...state, count: state.count + 1 };
    case 'DECREMENT':
      return { ...state, count: state.count - 1 };
    default:
      return state;
  }
}

// userReducer.js
const initialUserState = { user: null };

export function userReducer(state = initialUserState, action) {
  switch (action.type) {
    case 'SET_USER':
      return { ...state, user: action.payload };
    default:
      return state;
  }
}

组合reducers

// rootReducer.js
import { combineReducers } from 'redux';
import { counterReducer } from './counterReducer';
import { userReducer } from './userReducer';

const rootReducer = combineReducers({
  counter: counterReducer,
  user: userReducer
});

export default rootReducer;

创建store

// store.js
import { createStore } from 'redux';
import rootReducer from './rootReducer';

const store = createStore(rootReducer);

export default store;

使用store

// App.js
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';

function App() {
  const count = useSelector(state => state.counter.count);
  const user = useSelector(state => state.user.user);
  const dispatch = useDispatch();

  const increment = () => {
    dispatch({ type: 'INCREMENT' });
  };

  const setUser = (user) => {
    dispatch({ type: 'SET_USER', payload: user });
  };

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={increment}>Increment</button>

      <h1>User: {user ? user.name : 'No user logged in'}</h1>
      <button onClick={() => setUser({ name: 'John Doe' })}>Set User</button>
    </div>
  );
}

export default App;

中间件和异步操作

// store.js
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './rootReducer';

const store = createStore(rootReducer, applyMiddleware(thunk));

export default store;

// store.js
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './rootReducer';

const store = createStore(rootReducer, applyMiddleware(thunk));

export default store;

2. Vue中模块分割

在VueX中为了避免store带来的复杂性,Vuex提供了模块化功能,可以将单一的store分割成多个模块,每个模块负责管理应用的不同部分,但是这些模块属于同一个store。

const moduleA = {
  state: () => ({
    // 模块 A 的状态
  }),
  mutations: {
    // 模块 A 的突变
  },
  actions: {
    // 模块 A 的异步操作
  },
  getters: {
    // 模块 A 的计算属性
  }
};

const moduleB = {
  state: () => ({
    // 模块 B 的状态
  }),
  mutations: {
    // 模块 B 的突变
  },
  actions: {
    // 模块 B 的异步操作
  },
  getters: {
    // 模块 B 的计算属性
  }
};

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
});

为什么pinia可以有多个store?

Pinia允许创建多个store。Pinia的设计目标之一就是灵活性和简洁性,它采用模块化的方式管理状态,使得每个模块可以有自己独立的store。

1. 模块化设计:

  • Pinia的核心设计理念就是模块化。每个store都是独立的模块,负责管理其特定的状态和逻辑。
  • 这种设计模式使得状态管理更加灵活,可以根据应用的不同部分创建不同的store,每个store只关注其相关的状态和操作。

2. 简化依赖注入:

  • 在大型应用中,使用多个store可以简化依赖注入和管理。每个组件或模块只需要注入它所需的store,而不是整个全局状态树。
  • 这使得代码更加模块化和可维护。

3. 独立性和复用性:

  • 使用多个store可以提高状态管理的独立性和复用性。不同的store可以在不同的应用或不同的组件中复用,减少耦合度。

4. 按需加载:

  • 在需要时才创建和加载store,可以减少初始化加载时间和内存占用,提高性能。
import { createApp } from 'vue';
import { createPinia, defineStore } from 'pinia';
import App from './App.vue';

const app = createApp(App);

// 创建 Pinia 实例
const pinia = createPinia();
app.use(pinia);

// 定义第一个 store
const useStoreA = defineStore('storeA', {
  state: () => ({
    count: 0
  }),
  actions: {
    increment() {
      this.count++;
    }
  }
});

// 定义第二个 store
const useStoreB = defineStore('storeB', {
  state: () => ({
    name: 'Pinia'
  }),
  actions: {
    updateName(newName) {
      this.name = newName;
    }
  }
});

// 在组件中使用 store
export default {
  setup() {
    const storeA = useStoreA();
    const storeB = useStoreB();

    return {
      storeA,
      storeB
    };
  }
};

app.mount('#app');

与Vuex,Redux的对比

1. 单一store vs 多store

  • Vuex,Redux通常使用一个全局store,将所有状态集中管理。
  • Pinia使用多个独立的store,每个store管理其特定的状态和逻辑。

2. 单一store vs 多store

  • Vuex,Redux可以通过模块化配置将状态分割成多个模块,但这些模块属于一个全局store。
  • Pinia通过多个store实现模块化,每个store都是独立的。