前言:在頁面加入自適應是提高用戶體驗的一種形式,甚至有時候是手機用戶,我們就需要做一個自適應處理,其中肯定會涉及一些狀態條件的判斷,而這些關鍵的條件就是我們用來切換樣式的關鍵,所以我們需要使用狀態管理工具vuex或者pinia進行存儲這些狀態,方便可以根據這些狀態來控制顯示和隱藏。
項目的使用:因為我們搭建的是vue3項目,推薦使用pinia,當然我也會簡單介紹下vuex。
一、基本思路
1.顯示頁面:是由layout組件控制,則對這個組件進行自適應化。
2.在組件中設置一些狀態通過v-if來控制某個組件的顯示和隱藏,比如當設備過小時,隱藏側邊欄,使用一個小小的展開圖標代替。
3.狀態通過pinia來管理。
4.在組件掛載之前在window對象上加上resize方法監聽頁面的變化,再根據不同的變化配合pinia設置不同的狀態并存儲。
5.樣式使用scss,樣式做全局聲明,變量化,方便統一修改和配置。
6.根據不同的設備尺寸變化設置、加載、切換不同的css樣式。
二、vuex與pinia
Vuex 和 Pinia 都是 Vue 生態中用于狀態管理的工具,簡單說就是用來管理組件之間共享的數據(比如用戶信息、購物車數據等)。它們解決的核心問題是:當多個組件需要使用同一數據時,如何讓數據變更更清晰、更易維護。
2.1 Vuex(“老大哥”,Vue 2 時代主流)
Vuex 是 Vue 官方早期推出的狀態管理庫,主要用于 Vue 2,雖然也能在 Vue 3 中使用,但現在更推薦 Pinia。
1. 核心概念(必須掌握)
Vuex 的狀態管理遵循 “單向數據流”,核心結構包含 5 個部分:
State:存儲共享數據的地方(類似組件的?
data
)。// 示例:store/index.js import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex)const store = new Vuex.Store({state: {count: 0, // 共享的計數器user: null // 共享的用戶信息} })
Mutations:唯一能修改?
state
?的地方,必須是同步函數(類似組件的?methods
,但只能修改狀態)。mutations: {increment(state) {state.count++ // 只能通過 mutation 修改 state},setUser(state, userInfo) {state.user = userInfo // 可以接收參數} }
Actions:處理異步操作(比如請求接口),最終通過調用?
mutations
?修改?state
(不能直接改?state
)。actions: {// 異步登錄login(context, { username, password }) {return new Promise((resolve) => {// 模擬接口請求setTimeout(() => {const user = { id: 1, name: username }context.commit('setUser', user) // 調用 mutation 修改狀態resolve(user)}, 1000)})} }
Getters:類似組件的?
computed
,用于對?state
?進行加工處理(比如篩選、計算)。getters: {doubleCount(state) {return state.count * 2 // 計算 count 的兩倍},isLogin(state) {return !!state.user // 判斷用戶是否登錄} }
Modules:當狀態太多時,拆分模塊(比如拆成?
user
?模塊、cart
?模塊)。modules: {user: {namespaced: true, // 開啟命名空間,避免沖突state: { name: '' },mutations: { setName(state, name) { state.name = name } }} }
2. 如何在組件中使用?
讀取?
state
?或?getters
:<template><div>計數:{{ $store.state.count }}兩倍計數:{{ $store.getters.doubleCount }}</div> </template>
調用?
mutations
?或?actions
:<script> export default {methods: {add() {this.$store.commit('increment') // 調用 mutation},async login() {await this.$store.dispatch('login', { username: 'admin' }) // 調用 action}} } </script>
簡化寫法(推薦):用?
mapState
、mapActions
?等輔助函數:<script> import { mapState, mapActions } from 'vuex' export default {computed: {...mapState(['count']) // 映射 state.count 到組件的 count},methods: {...mapActions(['login']) // 映射 action login 到組件方法} } </script>
3. 優缺點
- 優點:成熟穩定,文檔豐富,適合大型項目,支持嚴格模式(禁止直接修改?
state
)。 - 缺點:
- 寫法繁瑣,需要定義?
mutations
、actions
?等,模板代碼多。 - 對 TypeScript 支持差,類型推斷不友好。
- 必須通過?
this.$store
?訪問,不夠靈活。
- 寫法繁瑣,需要定義?
2.2 Pinia(“新寵”,Vue 3 官方推薦)
Pinia 是 Vue 官方推出的新一代狀態管理庫,由 Vuex 作者開發,現在是 Vue 3 推薦的狀態管理方案,也支持 Vue 2。
1. 核心概念(比 Vuex 簡單)
Pinia 簡化了 Vuex 的設計,取消了?mutations
,只有 3 個核心概念:
- Store:一個存儲狀態的容器,每個模塊對應一個?
store
(類似 Vuex 的?modules
,但更靈活)。 - State:存儲數據的地方(和 Vuex 的?
state
?類似)。 - Actions:處理同步 / 異步操作,并直接修改?
state
(合并了 Vuex 的?mutations
?和?actions
)。 - Getters:類似 Vuex 的?
getters
,用于計算狀態。
2. 基本使用步驟
步驟 1:安裝
npm install pinia --save
步驟 2:創建 Pinia 實例并掛載
在?main.js
?中:
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'const app = createApp(App)
app.use(createPinia()) // 掛載 Pinia
app.mount('#app')
步驟 3:定義一個 Store(比如?store/counter.js
)
import { defineStore } from 'pinia'// 定義一個 store,命名規范:useXXXStore
export const useCounterStore = defineStore('counter', {// 狀態(類似 data)state: () => ({count: 0,user: null}),// 計算屬性(類似 computed)getters: {doubleCount: (state) => state.count * 2,isLogin: (state) => !!state.user},// 方法(同步/異步都可以,類似 methods)actions: {increment() {this.count++ // 直接修改 state(不需要 mutation)},// 異步操作async login(username, password) {// 模擬接口請求const user = await new Promise((resolve) => {setTimeout(() => resolve({ id: 1, name: username }), 1000)})this.user = user // 直接修改 state}}
})
3. 在組件中使用
<template><div>計數:{{ counterStore.count }}兩倍計數:{{ counterStore.doubleCount }}<button @click="counterStore.increment">+1</button><button @click="handleLogin">登錄</button></div>
</template><script setup>
import { useCounterStore } from '@/store/counter'// 獲取 store 實例
const counterStore = useCounterStore()// 調用異步 action
const handleLogin = async () => {await counterStore.login('admin', '123456')
}
</script>
4. 高級用法
修改狀態的其他方式:
// 方式1:直接修改 counterStore.count = 10// 方式2:批量修改(適合多個狀態同時更新) counterStore.$patch({count: 10,user: { name: 'new name' } })// 方式3:通過函數修改(復雜邏輯) counterStore.$patch((state) => {state.count += 10state.user.name = 'new name' })
模塊化:直接創建多個?
store
?文件即可(比如?userStore.js
、cartStore.js
),無需像 Vuex 那樣用?modules
?嵌套。持久化:配合?
pinia-plugin-persistedstate
?插件,輕松實現狀態持久化(刷新頁面不丟失):npm install pinia-plugin-persistedstate --save
// 在 store 中開啟持久化 export const useUserStore = defineStore('user', {state: () => ({ user: null }),persist: true // 開啟持久化,默認存儲到 localStorage })
5. 優缺點
- 優點:
- 寫法簡潔,取消了?
mutations
,直接在?actions
?中修改狀態。 - 完美支持 TypeScript,類型推斷友好。
- 支持 Vue 2 和 Vue 3,遷移成本低。
- 無需?
this.$store
,直接導入?store
?實例使用,更靈活。 - 內置模塊化,無需額外配置。
- 寫法簡潔,取消了?
- 缺點:
- 相對較新,某些老項目可能還在使用 Vuex。
- 生態不如 Vuex 成熟(但主流功能都有替代方案)。
三、Vuex vs Pinia 核心區別
特性 | Vuex | Pinia |
---|---|---|
核心概念 | State、Mutations、Actions、Getters、Modules | State、Actions、Getters(無 Mutations,Modules 被 Store 替代) |
異步操作 | 必須在 Actions 中處理,通過 Mutations 修改狀態 | 直接在 Actions 中處理并修改狀態 |
TypeScript 支持 | 差 | 優秀 |
寫法簡潔度 | 繁瑣(需定義 Mutations) | 簡潔(直接修改狀態) |
模塊化 | 需要?modules ?配置 | 每個 Store 就是一個模塊 |
適用版本 | Vue 2 為主,Vue 3 兼容 | Vue 3 推薦,Vue 2 兼容 |
四、如何選擇?
- 新項目(尤其是 Vue 3 + TypeScript):優先用 Pinia,寫法簡單,未來趨勢。
- 老項目(Vue 2):如果已用 Vuex,繼續維護即可;如果新開發,也可以用 Pinia(支持 Vue 2)。
- 團隊熟悉 Vuex:如果團隊對 Vuex 更熟練,且項目穩定,無需強制遷移。