惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
Microsoft Security Blog
Microsoft Security Blog
大猫的无限游戏
大猫的无限游戏
B
Blog RSS Feed
MyScale Blog
MyScale Blog
博客园_首页
S
SegmentFault 最新的问题
WordPress大学
WordPress大学
小众软件
小众软件
V
Visual Studio Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Vercel News
Vercel News
Hugging Face - Blog
Hugging Face - Blog
The GitHub Blog
The GitHub Blog
D
Docker
宝玉的分享
宝玉的分享
博客园 - 【当耐特】
F
Fortinet All Blogs
V
V2EX
Last Week in AI
Last Week in AI
Blog — PlanetScale
Blog — PlanetScale
Microsoft Azure Blog
Microsoft Azure Blog
IT之家
IT之家
雷峰网
雷峰网
博客园 - 叶小钗
月光博客
月光博客
J
Java Code Geeks
量子位
爱范儿
爱范儿
阮一峰的网络日志
阮一峰的网络日志
Martin Fowler
Martin Fowler
H
Help Net Security
酷 壳 – CoolShell
酷 壳 – CoolShell
腾讯CDC
Latest news
Latest news
Recent Announcements
Recent Announcements
Google DeepMind News
Google DeepMind News
美团技术团队
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
The Blog of Author Tim Ferriss
T
Troy Hunt's Blog
B
Blog
T
Tenable Blog
S
Schneier on Security
L
LangChain Blog
L
LINUX DO - 热门话题
博客园 - 司徒正美
I
InfoQ
P
Privacy International News Feed
P
Privacy & Cybersecurity Law Blog

吖远zzyの博客

记录一下豆包视频去水印的研究过程,以及fallback_api加密数据qAAB开头数据的解密。 | 吖远zzyの博客 解决华为开发者工具 DevEco Studio 登录跳转 localhost:10101 端口被阻止问题 | 吖远zzyの博客 微信小程序个人资质审核血泪史:踩坑,从反复被拒到神奇过审 | 吖远zzyの博客 如何实现公众号自动回复或做一个短视频无水印解析机器人? | 吖远zzyの博客 以后在手机上用 Termux 和 GitHub Actions 更新 Hexo 博客 | 吖远zzyの博客 必备!这款万能小程序能给抖音/豆包视频图集去除水印、还有有趣的测反应、玩成语模拟工具。 自制的一些免费API接口第二弹(获取QQ昵称、头像、抖音/豆包视频去水印等...) 告别原生导航栏:微信小程序自定义导航栏完美适配方案 在安卓手机上运行OpenClaw?当然可以,用Termux折腾OpenClaw安装QQ机器人的踩坑记录... | 吖远zzyの博客 个人开发工具之抖音直播录制工具:一款功能强大的Android直播录制应用 UniApp中Canvas绘图的易错点与踩坑指南 QQ频道机器人与UniApp开发:常见踩坑点与解决方案 UniApp中Canvas绘图不显示的常见问题与解决方案 Hexo博客实现随机文章功能的完整教程 QQ频道机器人Android客户端使用指南 | 吖远zzyの博客 安卓版QQ频道机器人APP客户端插件开发指南 | 吖远zzyの博客 2024年AI编程助手深度评测:哪款最适合你? uni-app地图定位踩坑记:地图功能和定位的那些坑 uni-app文件上传踩坑记:图片处理和上传全攻略 uni-app表单验证踩坑记:这些坑我替你踩过了 uni-app开发踩坑记录:新手必看的常见问题与解决方案 uni-app安全防护指南:构建可靠的跨端应用 uni-app性能优化指南:从加载到渲染的全方位提升 uni-app动画效果实战:从基础到高级的动画实现指南 uni-app组件开发实战:从基础到进阶的最佳实践 uni-app网络请求与缓存策略:构建高效的数据层 uni-app路由与页面跳转:最佳实践与踩坑指南
uni-app状态管理进阶:Vuex最佳实践与性能优化
吖远zzy · 2024-03-20 · via 吖远zzyの博客
  1. 1. 1. Vuex基础配置
    1. 1.1. 1.1 目录结构
    2. 1.2. 1.2 基础配置
  2. 2. 2. 模块化设计
    1. 2.1. 2.1 用户模块
    2. 2.2. 2.2 购物车模块
  3. 3. 3. 数据持久化
    1. 3.1. 3.1 插件封装
    2. 3.2. 3.2 使用插件
  4. 4. 4. 性能优化
    1. 4.1. 4.1 避免频繁更新
    2. 4.2. 4.2 批量更新
  5. 5. 5. 辅助函数使用
    1. 5.1. 5.1 组件中使用
    2. 5.2. 5.2 自定义辅助函数
  6. 6. 6. 最佳实践建议
  7. 7. 7. 总结

uni-app状态管理进阶:Vuex最佳实践与性能优化 0 次阅读

状态管理是uni-app应用开发中的重要环节,本文将深入介绍Vuex在uni-app中的应用,以及如何构建高效的数据流方案。

1. Vuex基础配置

1.1 目录结构

1
2
3
4
5
6
7
8
9
10
store
├── index.js # 入口文件
├── state.js # 根级别的state
├── mutations.js # 根级别的mutations
├── actions.js # 根级别的actions
├── getters.js # 根级别的getters
└── modules # 模块目录
├── user.js # 用户模块
├── cart.js # 购物车模块
└── order.js # 订单模块

1.2 基础配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import mutations from './mutations'
import actions from './actions'
import getters from './getters'
import user from './modules/user'
import cart from './modules/cart'
import order from './modules/order'

Vue.use(Vuex)

const store = new Vuex.Store({
state,
mutations,
actions,
getters,
modules: {
user,
cart,
order
},
strict: process.env.NODE_ENV !== 'production'
})

export default store

2. 模块化设计

2.1 用户模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// store/modules/user.js
import { login, getUserInfo, updateUserInfo } from '@/api/user'

const state = {
token: uni.getStorageSync('token') || '',
userInfo: null,
permissions: []
}

const mutations = {
SET_TOKEN(state, token) {
state.token = token
uni.setStorageSync('token', token)
},
SET_USER_INFO(state, info) {
state.userInfo = info
},
SET_PERMISSIONS(state, permissions) {
state.permissions = permissions
},
CLEAR_USER_DATA(state) {
state.token = ''
state.userInfo = null
state.permissions = []
uni.removeStorageSync('token')
}
}

const actions = {
// 登录
async login({ commit }, params) {
try {
const { token } = await login(params)
commit('SET_TOKEN', token)
return token
} catch (err) {
throw new Error('登录失败')
}
},

// 获取用户信息
async getUserInfo({ commit }) {
try {
const { userInfo, permissions } = await getUserInfo()
commit('SET_USER_INFO', userInfo)
commit('SET_PERMISSIONS', permissions)
return userInfo
} catch (err) {
throw new Error('获取用户信息失败')
}
},

// 更新用户信息
async updateUserInfo({ commit }, params) {
try {
const info = await updateUserInfo(params)
commit('SET_USER_INFO', info)
return info
} catch (err) {
throw new Error('更新用户信息失败')
}
},

// 退出登录
logout({ commit }) {
commit('CLEAR_USER_DATA')
}
}

const getters = {
isLogin: state => !!state.token,
userInfo: state => state.userInfo || {},
permissions: state => state.permissions
}

export default {
namespaced: true,
state,
mutations,
actions,
getters
}

2.2 购物车模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// store/modules/cart.js
import { getCartList, updateCart, removeFromCart } from '@/api/cart'

const state = {
cartList: [],
selectedIds: []
}

const mutations = {
SET_CART_LIST(state, list) {
state.cartList = list
},
UPDATE_CART_ITEM(state, { id, data }) {
const index = state.cartList.findIndex(item => item.id === id)
if (index > -1) {
state.cartList[index] = { ...state.cartList[index], ...data }
}
},
REMOVE_CART_ITEM(state, id) {
state.cartList = state.cartList.filter(item => item.id !== id)
},
SET_SELECTED_IDS(state, ids) {
state.selectedIds = ids
}
}

const actions = {
// 获取购物车列表
async getCartList({ commit }) {
try {
const list = await getCartList()
commit('SET_CART_LIST', list)
return list
} catch (err) {
throw new Error('获取购物车列表失败')
}
},

// 更新购物车商品
async updateCartItem({ commit }, { id, data }) {
try {
await updateCart(id, data)
commit('UPDATE_CART_ITEM', { id, data })
} catch (err) {
throw new Error('更新购物车商品失败')
}
},

// 删除购物车商品
async removeCartItem({ commit }, id) {
try {
await removeFromCart(id)
commit('REMOVE_CART_ITEM', id)
} catch (err) {
throw new Error('删除购物车商品失败')
}
}
}

const getters = {
cartCount: state => state.cartList.length,
selectedCount: state => state.selectedIds.length,
totalPrice: state => {
return state.cartList
.filter(item => state.selectedIds.includes(item.id))
.reduce((total, item) => total + item.price * item.quantity, 0)
}
}

export default {
namespaced: true,
state,
mutations,
actions,
getters
}

3. 数据持久化

3.1 插件封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// store/plugins/persist.js
const STORAGE_KEY = 'vuex_storage'

export default function createPersistPlugin(options = {}) {
const {
key = STORAGE_KEY,
paths = [],
storage = uni.getStorageSync
} = options

// 获取持久化数据
const getState = () => {
try {
const data = storage(key)
return data ? JSON.parse(data) : {}
} catch (err) {
console.error('获取持久化数据失败:', err)
return {}
}
}

// 设置持久化数据
const setState = (state, paths) => {
try {
const data = paths.length
? paths.reduce((obj, path) => {
obj[path] = state[path]
return obj
}, {})
: state
storage(key, JSON.stringify(data))
} catch (err) {
console.error('设置持久化数据失败:', err)
}
}

return store => {
// 初始化时获取持久化数据
const data = getState()
if (Object.keys(data).length > 0) {
store.replaceState({
...store.state,
...data
})
}

// 监听数据变化
store.subscribe((mutation, state) => {
setState(state, paths)
})
}
}

3.2 使用插件

1
2
3
4
5
6
7
8
9
10
11
12
// store/index.js
import createPersistPlugin from './plugins/persist'

const persistPlugin = createPersistPlugin({
paths: ['user.token', 'user.userInfo', 'cart.cartList'],
storage: uni.setStorageSync
})

const store = new Vuex.Store({
// ...其他配置
plugins: [persistPlugin]
})

4. 性能优化

4.1 避免频繁更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// store/modules/cart.js
import { debounce } from '@/utils/tools'

const actions = {
// 使用防抖优化更新
updateCartItem: debounce(async function({ commit }, { id, data }) {
try {
await updateCart(id, data)
commit('UPDATE_CART_ITEM', { id, data })
} catch (err) {
throw new Error('更新购物车商品失败')
}
}, 300)
}

4.2 批量更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// store/modules/cart.js
const actions = {
// 批量更新购物车
async batchUpdateCart({ commit }, items) {
try {
await Promise.all(items.map(item => updateCart(item.id, item.data)))
items.forEach(item => {
commit('UPDATE_CART_ITEM', item)
})
} catch (err) {
throw new Error('批量更新购物车失败')
}
}
}

5. 辅助函数使用

5.1 组件中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<template>
<view class="cart">
<view class="total">总价: ¥{{ totalPrice }}</view>
<view
v-for="item in cartList"
:key="item.id"
class="cart-item"
>
<text>{{ item.name }}</text>
<text>¥{{ item.price }}</text>
<button @click="updateQuantity(item.id, item.quantity + 1)">+</button>
<text>{{ item.quantity }}</text>
<button @click="updateQuantity(item.id, item.quantity - 1)">-</button>
<button @click="removeItem(item.id)">删除</button>
</view>
</view>
</template>

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

export default {
computed: {
...mapState('cart', ['cartList']),
...mapGetters('cart', ['totalPrice'])
},
methods: {
...mapActions('cart', ['updateCartItem', 'removeCartItem']),
async updateQuantity(id, quantity) {
if (quantity < 1) return
try {
await this.updateCartItem({ id, data: { quantity } })
uni.showToast({ title: '更新成功' })
} catch (err) {
uni.showToast({ title: err.message, icon: 'none' })
}
},
async removeItem(id) {
try {
await this.removeCartItem(id)
uni.showToast({ title: '删除成功' })
} catch (err) {
uni.showToast({ title: err.message, icon: 'none' })
}
}
}
}
</script>

5.2 自定义辅助函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// store/helpers.js
export function mapCache(namespace, maps) {
const res = {}

normalizeMap(maps).forEach(({ key, val }) => {
res[key] = function mappedCache() {
const store = this.$store
const cache = store._cache || (store._cache = {})
const cacheKey = namespace + ':' + key

if (cache[cacheKey]) {
return cache[cacheKey]
}

const value = typeof val === 'function'
? val.call(this, store.state[namespace], store.getters)
: store.state[namespace][val]

cache[cacheKey] = value
return value
}
})

return res
}

function normalizeMap(map) {
return Array.isArray(map)
? map.map(key => ({ key, val: key }))
: Object.keys(map).map(key => ({ key, val: map[key] }))
}

6. 最佳实践建议

  1. 合理划分模块
  2. 实现数据持久化
  3. 注意性能优化
  4. 使用辅助函数
  5. 做好错误处理

7. 总结

  1. 掌握Vuex基础配置
  2. 实现模块化设计
  3. 处理数据持久化
  4. 优化更新性能
  5. 灵活使用辅助函数

如果觉得文章对你有帮助,欢迎点赞、评论、分享,你的支持是我继续创作的动力!