在 Vue2 + Uniapp 项目中使用 Vuex 进行状态管理,以下是详细的使用方法:

1. 安装 Vuex

首先确保已安装 Vuex:

npm install vuex@3.6.2  # Vue2 对应 Vuex3

2. 创建 Vuex Store

在项目根目录下创建 store 文件夹,然后创建 index.js

// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0,
    userInfo: null
  },
  mutations: {
    increment(state) {
      state.count++
    },
    setUserInfo(state, payload) {
      state.userInfo = payload
    }
  },
  actions: {
    async fetchUserInfo({ commit }, userId) {
      // 这里可以调用接口获取用户信息
      const userInfo = await uni.request({
        url: 'https://api.example.com/user/' + userId
      })
      commit('setUserInfo', userInfo)
    }
  },
  getters: {
    doubleCount: state => state.count * 2,
    isLoggedIn: state => !!state.userInfo
  }
})

export default store

3. 在 main.js 中引入 Store

// main.js
import Vue from 'vue'
import App from './App'
import store from './store'

Vue.config.productionTip = false

const app = new Vue({
  store,
  ...App
})
app.$mount()

4. 在组件中使用 Vuex

访问 State

// 在组件中
computed: {
  count() {
    return this.$store.state.count
  },
  // 使用 mapState 辅助函数
  ...mapState(['count', 'userInfo'])
}

提交 Mutation

methods: {
  increment() {
    this.$store.commit('increment')
  },
  // 使用 mapMutations 辅助函数
  ...mapMutations(['increment', 'setUserInfo'])
}

分发 Action

methods: {
  fetchUser() {
    this.$store.dispatch('fetchUserInfo', '123')
  },
  // 使用 mapActions 辅助函数
  ...mapActions(['fetchUserInfo'])
}

使用 Getter

computed: {
  doubleCount() {
    return this.$store.getters.doubleCount
  },
  // 使用 mapGetters 辅助函数
  ...mapGetters(['doubleCount', 'isLoggedIn'])
}

5. 模块化 Vuex

对于大型项目,建议将 store 分割成模块:

// store/modules/user.js
export default {
  namespaced: true,
  state: () => ({
    token: null,
    profile: null
  }),
  mutations: {
    setToken(state, token) {
      state.token = token
    }
  },
  actions: {
    login({ commit }, credentials) {
      // 登录逻辑
    }
  }
}

// store/index.js
import user from './modules/user'

const store = new Vuex.Store({
  modules: {
    user
  }
})

在组件中使用带命名空间的模块:

computed: {
  ...mapState('user', ['token']),
  ...mapGetters('user', ['isAuthenticated'])
},
methods: {
  ...mapActions('user', ['login'])
}

6. Uniapp 中的注意事项

  1. 持久化存储​:小程序关闭后 Vuex 状态会重置,需要配合本地存储:
// 在 app.vue 的 onLaunch 中
onLaunch() {
  const state = uni.getStorageSync('vuex_state')
  if (state) {
    this.$store.replaceState(state)
  }
  
  // 监听 store 变化
  this.$store.subscribe((mutation, state) => {
    uni.setStorageSync('vuex_state', state)
  })
}
  1. 分包加载​:如果使用分包,确保主包加载 store

  2. 异步操作​:在小程序中,网络请求需要使用 uni.request 而不是 axios

7. 完整示例

<template>
  <view class="container">
    <text>Count: {{ count }}</text>
    <text>Double Count: {{ doubleCount }}</text>
    <button @click="increment">Increment</button>
    
    <view v-if="isLoggedIn">
      <text>Welcome, {{ userInfo.name }}</text>
    </view>
    <button v-else @click="fetchUser">Login</button>
  </view>
</template>

<script>
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'

export default {
  computed: {
    ...mapState(['count', 'userInfo']),
    ...mapGetters(['doubleCount', 'isLoggedIn'])
  },
  methods: {
    ...mapMutations(['increment']),
    ...mapActions(['fetchUserInfo']),
    
    fetchUser() {
      this.fetchUserInfo('123')
    }
  }
}
</script>

<style lang="scss" scoped>
.container {
  padding: 20px;
  
  text {
    display: block;
    margin-bottom: 10px;
  }
  
  button {
    margin-top: 10px;
    background-color: #007AFF;
    color: white;
    padding: 10px;
    border-radius: 5px;
  }
}
</style>

以上就是在 Vue2 + Uniapp 项目中使用 Vuex 的完整指南。根据项目需求,你可以进一步扩展和优化 store 的结构。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐