uniapp 系统学习,从入门到实战(八)—— Vuex 的使用

发布于:2025-03-05 ⋅ 阅读:(17) ⋅ 点赞:(0)

全篇大概 4500 字(含代码),建议阅读时间 30min


📚 目录

  1. Vuex核心概念解析
  2. 在 UniApp 中集成Vuex
  3. 状态管理与数据共享实践
  4. 总结

一、Vuex 核心概念解析

1.1 什么是状态管理

在跨多组件的大型应用中,不同页面/组件需要共享和修改相同数据时,直接通过 Props/Event 传递会导致代码冗余和维护困难。Vuex 作为 ​集中式状态管理方案,通过统一存储和管理应用级状态,实现数据流的可预测性。

1.2 Vuex 五大核心概念

State(状态)
单一数据源,所有组件共享的数据存储对象

// store/index.js
export default new Vuex.Store({
  state: {
    userInfo: null,     // 用户信息
    cartItems: [],      // 购物车商品
    themeColor: '#42b983' // 全局主题色
  }
})

Getters(派生状态)
基于 State 的计算属性,用于派生复杂数据

getters: {
  totalPrice: state => {
    return state.cartItems.reduce((sum, item) => 
      sum + item.price * item.quantity, 0)
  },
  isLoggedIn: state => !!state.userInfo
}

Mutations(同步修改)
唯一修改 State 的方法,必须是同步函数

mutations: {
  SET_USER(state, user) {
    state.userInfo = user
  },
  ADD_TO_CART(state, product) {
    const item = state.cartItems.find(p => p.id === product.id)
    item ? item.quantity++ : state.cartItems.push({...product, quantity: 1})
  }
}

Actions(异步操作)
处理异步逻辑后提交 Mutations

actions: {
  async login({ commit }, credentials) {
    const res = await uni.request({
      url: '/api/login',
      method: 'POST',
      data: credentials
    })
    commit('SET_USER', res.data)
  }
}

Modules(模块化)
将复杂 Store 拆分为多个模块

// store/modules/cart.js
export default {
  namespaced: true,
  state: { items: [] },
  mutations: { /* ... */ }
}

二、在 UniApp 中集成 Vuex

2.1 安装与配置

步骤 1:安装依赖

npm install vuex --save

步骤 2:创建 Store 结构

├── store/
│   ├── index.js       # 主入口
│   ├── modules/       # 模块目录
│   │   └── user.js
│   └── types.js       # Mutation 类型常量

步骤 3:初始化 Store

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

Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
    user
  }
})

步骤 4:挂载到 UniApp

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

Vue.config.productionTip = false

App.mpType = 'app'

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

三、状态管理与数据共享实践

3.1 基础使用场景

场景 1:全局用户状态管理

<!-- pages/user/login.vue -->
<script>
export default {
  methods: {
    handleLogin() {
      this.$store.dispatch('user/login', {
        username: 'test',
        password: '123456'
      }).then(() => {
        uni.switchTab({ url: '/pages/home/index' })
      })
    }
  }
}
</script>

场景 2:跨页面共享购物车数据

// 组件中访问购物车
computed: {
  cartItems() {
    return this.$store.state.cart.items
  },
  total() {
    return this.$store.getters['cart/totalPrice']
  }
}

3.2 模块化高级实践

模块定义

// store/modules/user.js
export default {
  namespaced: true,
  state: () => ({
    token: uni.getStorageSync('token') || null,
    profile: null
  }),
  mutations: {
    SET_TOKEN(state, token) {
      state.token = token
      uni.setStorageSync('token', token)
    },
    SET_PROFILE(state, user) {
      state.profile = user
    }
  },
  actions: {
    async fetchProfile({ commit }) {
      const { data } = await uni.$http.get('/user/profile')
      commit('SET_PROFILE', data)
    }
  }
}

跨模块调用

// 在购物车模块中获取用户ID
actions: {
  async loadCart({ rootState, commit }) {
    const userId = rootState.user.profile.id
    const res = await uni.$http.get(`/cart/${userId}`)
    commit('INIT_CART', res.data)
  }
}

3.3 持久化存储方案

使用 vuex-persistedstate

npm install vuex-persistedstate

// store/index.js
import createPersistedState from 'vuex-persistedstate'

export default new Vuex.Store({
  plugins: [
    createPersistedState({
      key: 'my-app-store',
      paths: ['user.token', 'settings.theme'],
      storage: {
        getItem: key => uni.getStorageSync(key),
        setItem: (key, value) => uni.setStorageSync(key, value),
        removeItem: key => uni.removeStorageSync(key)
      }
    })
  ]
})

四、最佳实践与性能优化

4.1 代码组织规范

// store/types.js
export const SET_USER = 'user/SET_USER'
export const ADD_PRODUCT = 'cart/ADD_PRODUCT'

// 使用常量代替字符串
mutations: {
  [SET_USER](state, payload) { /* ... */ }
}

4.2 严格模式与调试

// 开发环境开启严格模式
export default new Vuex.Store({
  strict: process.env.NODE_ENV !== 'production'
})

4.3 性能优化策略

使用 mapState 辅助函数

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

export default {
  computed: {
    ...mapState(['themeColor']),
    ...mapGetters(['isLoggedIn'])
  }
}
</script>

避免过度渲染

// 使用 Object.assign 创建新引用
mutations: {
  UPDATE_ITEM(state, payload) {
    state.items = Object.assign({}, state.items, payload)
  }
}

五、实战案例:全局主题切换

5.1 Store 定义

// store/modules/settings.js
export default {
  namespaced: true,
  state: () => ({
    theme: 'light',
    colors: {
      light: { primary: '#42b983' },
      dark: { primary: '#34495e' }
    }
  }),
  mutations: {
    TOGGLE_THEME(state) {
      state.theme = state.theme === 'light' ? 'dark' : 'light'
    }
  }
}

5.2 组件中使用

<template>
  <view :style="{ backgroundColor: themeColor }">
    <button @click="toggleTheme">切换主题</button>
  </view>
</template>

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

export default {
  computed: {
    ...mapState('settings', ['theme', 'colors']),
    themeColor() {
      return this.colors[this.theme].primary
    }
  },
  methods: {
    ...mapMutations('settings', ['TOGGLE_THEME']),
    toggleTheme() {
      this.TOGGLE_THEME()
    }
  }
}
</script>

总结

通过 Vuex 在 UniApp 中实现状态管理,开发者可以:

  • 集中管理跨组件共享数据
  • 通过严格的修改流程保证数据可追溯
  • 实现高效的模块化开发
  • 结合 UniApp 特性处理多端存储

网站公告

今日签到

点亮在社区的每一天
去签到