全局状态管理 #
概述 #
在复杂应用中,需要在多个组件之间共享状态。Alpine.js 提供了多种全局状态管理方案,本章将介绍最佳实践。
状态管理策略 #
选择策略 #
| 场景 | 推荐方案 |
|---|---|
| 简单共享 | Alpine.store |
| 模块化状态 | 多个 Store |
| 复杂逻辑 | Store + Actions |
| 类型安全 | TypeScript + Store |
Alpine.store 进阶 #
模块化 Store #
javascript
document.addEventListener('alpine:init', () => {
Alpine.store('user', {
data: null,
token: localStorage.getItem('token'),
get isLoggedIn() {
return !!this.token && !!this.data
},
async login(credentials) {
const res = await fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(credentials)
})
const data = await res.json()
this.token = data.token
this.data = data.user
localStorage.setItem('token', data.token)
},
logout() {
this.token = null
this.data = null
localStorage.removeItem('token')
}
})
Alpine.store('cart', {
items: [],
add(product) {
const existing = this.items.find(i => i.id === product.id)
if (existing) {
existing.quantity++
} else {
this.items.push({ ...product, quantity: 1 })
}
},
remove(productId) {
this.items = this.items.filter(i => i.id !== productId)
},
get total() {
return this.items.reduce((sum, i) => sum + i.price * i.quantity, 0)
},
get count() {
return this.items.reduce((sum, i) => sum + i.quantity, 0)
},
clear() {
this.items = []
}
})
Alpine.store('notification', {
items: [],
add(message, type = 'info', duration = 3000) {
const id = Date.now()
this.items.push({ id, message, type })
if (duration > 0) {
setTimeout(() => this.remove(id), duration)
}
},
remove(id) {
this.items = this.items.filter(n => n.id !== id)
},
success(message) { this.add(message, 'success') },
error(message) { this.add(message, 'error', 5000) },
warning(message) { this.add(message, 'warning') },
info(message) { this.add(message, 'info') }
})
})
Store 持久化 #
javascript
Alpine.store('settings', {
data: {
theme: 'light',
language: 'zh-CN',
notifications: true
},
init() {
this.load()
},
load() {
const saved = localStorage.getItem('settings')
if (saved) {
this.data = { ...this.data, ...JSON.parse(saved) }
}
},
save() {
localStorage.setItem('settings', JSON.stringify(this.data))
},
update(key, value) {
this.data[key] = value
this.save()
}
})
状态管理模式 #
Flux 模式 #
javascript
Alpine.store('app', {
state: {
user: null,
posts: [],
loading: false,
error: null
},
actions: {
async fetchPosts() {
this.state.loading = true
this.state.error = null
try {
const res = await fetch('/api/posts')
this.state.posts = await res.json()
} catch (e) {
this.state.error = e.message
} finally {
this.state.loading = false
}
},
async createPost(post) {
const res = await fetch('/api/posts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(post)
})
const newPost = await res.json()
this.state.posts.unshift(newPost)
},
async deletePost(id) {
await fetch(`/api/posts/${id}`, { method: 'DELETE' })
this.state.posts = this.state.posts.filter(p => p.id !== id)
}
},
get posts() { return this.state.posts },
get loading() { return this.state.loading },
get error() { return this.state.error }
})
分层架构 #
javascript
const api = {
async getPosts() {
const res = await fetch('/api/posts')
return res.json()
},
async createPost(post) {
const res = await fetch('/api/posts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(post)
})
return res.json()
}
}
const postService = {
posts: [],
loading: false,
async load() {
this.loading = true
this.posts = await api.getPosts()
this.loading = false
},
async create(post) {
const newPost = await api.createPost(post)
this.posts.unshift(newPost)
}
}
Alpine.store('posts', postService)
状态同步 #
跨标签页同步 #
javascript
Alpine.store('sync', {
data: {},
init() {
this.load()
window.addEventListener('storage', (e) => {
if (e.key === 'sync_data') {
this.data = JSON.parse(e.newValue)
}
})
},
load() {
const saved = localStorage.getItem('sync_data')
if (saved) {
this.data = JSON.parse(saved)
}
},
save() {
localStorage.setItem('sync_data', JSON.stringify(this.data))
},
set(key, value) {
this.data[key] = value
this.save()
}
})
WebSocket 同步 #
javascript
Alpine.store('realtime', {
socket: null,
connected: false,
data: {},
init() {
this.connect()
},
connect() {
this.socket = new WebSocket('wss://example.com/ws')
this.socket.onopen = () => {
this.connected = true
}
this.socket.onclose = () => {
this.connected = false
setTimeout(() => this.connect(), 3000)
},
this.socket.onmessage = (event) => {
const { type, payload } = JSON.parse(event.data)
this.handleMessage(type, payload)
}
},
handleMessage(type, payload) {
switch (type) {
case 'update':
this.data = { ...this.data, ...payload }
break
case 'delete':
delete this.data[payload.id]
break
}
},
send(type, payload) {
if (this.connected) {
this.socket.send(JSON.stringify({ type, payload }))
}
}
})
实用示例 #
完整购物车系统 #
javascript
Alpine.store('cart', {
items: [],
init() {
this.load()
this.$watch('items', () => this.save())
},
load() {
const saved = localStorage.getItem('cart')
if (saved) {
this.items = JSON.parse(saved)
}
},
save() {
localStorage.setItem('cart', JSON.stringify(this.items))
},
add(product) {
const existing = this.items.find(i => i.id === product.id)
if (existing) {
existing.quantity++
} else {
this.items.push({ ...product, quantity: 1 })
}
this.notify('added', product)
},
remove(productId) {
const item = this.items.find(i => i.id === productId)
this.items = this.items.filter(i => i.id !== productId)
this.notify('removed', item)
},
updateQuantity(productId, quantity) {
const item = this.items.find(i => i.id === productId)
if (item) {
item.quantity = Math.max(0, quantity)
if (item.quantity === 0) {
this.remove(productId)
}
}
},
clear() {
this.items = []
this.notify('cleared')
},
get total() {
return this.items.reduce((sum, i) => sum + i.price * i.quantity, 0)
},
get count() {
return this.items.reduce((sum, i) => sum + i.quantity, 0)
},
notify(event, data) {
window.dispatchEvent(new CustomEvent(`cart:${event}`, { detail: data }))
}
})
用户认证系统 #
javascript
Alpine.store('auth', {
user: null,
token: null,
loading: false,
init() {
this.token = localStorage.getItem('token')
if (this.token) {
this.fetchUser()
}
},
get isAuthenticated() {
return !!this.user
},
async login(credentials) {
this.loading = true
try {
const res = await fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(credentials)
})
if (!res.ok) throw new Error('登录失败')
const data = await res.json()
this.token = data.token
this.user = data.user
localStorage.setItem('token', data.token)
return true
} catch (e) {
console.error(e)
return false
} finally {
this.loading = false
}
},
async logout() {
await fetch('/api/logout', {
method: 'POST',
headers: { 'Authorization': `Bearer ${this.token}` }
})
this.user = null
this.token = null
localStorage.removeItem('token')
},
async fetchUser() {
try {
const res = await fetch('/api/user', {
headers: { 'Authorization': `Bearer ${this.token}` }
})
if (res.ok) {
this.user = await res.json()
} else {
this.logout()
}
} catch (e) {
this.logout()
}
}
})
表单状态管理 #
javascript
Alpine.store('form', {
forms: {},
register(name, initialValues = {}) {
this.forms[name] = {
values: { ...initialValues },
errors: {},
touched: {},
dirty: false,
submitting: false
}
},
getForm(name) {
return this.forms[name]
},
setValue(formName, field, value) {
const form = this.forms[formName]
if (form) {
form.values[field] = value
form.dirty = true
}
},
setTouched(formName, field) {
const form = this.forms[formName]
if (form) {
form.touched[field] = true
}
},
setError(formName, field, error) {
const form = this.forms[formName]
if (form) {
form.errors[field] = error
}
},
clearErrors(formName) {
const form = this.forms[formName]
if (form) {
form.errors = {}
}
},
reset(formName) {
const form = this.forms[formName]
if (form) {
form.values = {}
form.errors = {}
form.touched = {}
form.dirty = false
form.submitting = false
}
},
async submit(formName, onSubmit) {
const form = this.forms[formName]
if (form) {
form.submitting = true
try {
await onSubmit(form.values)
this.reset(formName)
} finally {
form.submitting = false
}
}
}
})
最佳实践 #
1. 单一职责 #
javascript
Alpine.store('user', { /* 用户相关 */ })
Alpine.store('cart', { /* 购物车相关 */ })
Alpine.store('notification', { /* 通知相关 */ })
2. 封装 API 调用 #
javascript
Alpine.store('posts', {
posts: [],
async fetch() {
this.posts = await api.getPosts()
},
async create(post) {
const newPost = await api.createPost(post)
this.posts.unshift(newPost)
}
})
3. 使用 getter #
javascript
Alpine.store('cart', {
items: [],
get total() {
return this.items.reduce((sum, i) => sum + i.price, 0)
},
get isEmpty() {
return this.items.length === 0
}
})
4. 错误处理 #
javascript
Alpine.store('data', {
items: [],
error: null,
async fetch() {
try {
const res = await fetch('/api/data')
this.items = await res.json()
} catch (e) {
this.error = e.message
}
}
})
小结 #
全局状态管理要点:
- 使用
Alpine.store管理全局状态 - 按功能模块拆分 Store
- 封装 API 调用和业务逻辑
- 使用 getter 封装计算逻辑
- 实现持久化和同步机制
下一章,我们将学习性能优化。
最后更新:2026-03-28