הגדרת ניהול מצב (Pinia) עבור יישומי Vue

סנכרון מצב בין רכיבי יישום Vue הופך לעיתים קרובות לכאוס, במיוחד כאשר יש לשמר נתונים בין הפעלות ולעבוד עם TypeScript. אנו מגדירים את Pinia, ניהול מצב מודרני עבור Vue 3, תוך ניתוח הלוגיקה העסקית וקביעה היכן נדרשת שמירה. הצוות שלנו מספק פרויקט סוהר: מהתקנה והגדרת טיפוסים ועד ליישום ותמיכה מתמשכת, תוך הבטחת פתרון אמין וניתן להרחבה.

פיתוח ותחזוקה של כל סוגי האתרים:

אתרי מידע או יישומי אינטרנט
אתרי תדמית, דפי נחיתה, אתרי חברה, קטלוגים מקוונים, חידונים, אתרי קידום, בלוגים, מקורות חדשות, פורטלי מידע, פורומים, אגרגטורים
אתרי מסחר אלקטרוני או יישומי אינטרנט
חנויות מקוונות, פורטלי B2B, שווקים, בורסות מקוונות, אתרי קאשבק, בורסות, פלטפורמות דרופשיפינג, מנתחי מוצרים
יישומי אינטרנט לניהול תהליכים עסקיים
מערכות CRM, מערכות ERP, פורטלים ארגוניים, מערכות ניהול ייצור, מנתחי מידע
אתרי שירות אלקטרוני או יישומי אינטרנט
פלטפורמות מודעות, בתי ספר מקוונים, בתי קולנוע מקוונים, בוני אתרים, פורטלים לשירותים אלקטרוניים, פלטפורמות אירוח וידאו, פורטלים נושאיים

אלה רק חלק מהסוגים הטכניים של אתרים שאנו עובדים איתם, ולכל אחד מהם יכולים להיות מאפיינים ופונקציונליות ספציפיים משלו, וכן ניתן להתאים אותם לצרכים ולמטרות הספציפיים של הלקוח.

השירותים שאנו מציעים
מציג 1 מתוך 1כל 2062 השירותים
הגדרת ניהול מצב (Pinia) עבור יישומי Vue
פשוט
מ- 4 שעות עד 2 ימים

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1365
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113
  • פיתוח אתר עבור SBH Partners
    פיתוח אתר עבור SBH Partners
    1201
  • פיתוח אתר עבור Red Pear
    פיתוח אתר עבור Red Pear
    619

הגדרת ניהול מצב (Pinia) עבור יישומי Vue

סנכרון מצב בין עשרות רכיבים הוא כאב ראש. במיוחד כשהנתונים צריכים להישמר בין הפעלות ו-TypeScript זורק שגיאות בכל צעד. ניסינו את כל הגישות: Vuex, EventBus, אפילו Provide/Inject—והתמקמנו על Pinia. המדידות שלנו מראות שקוד מבוסס Pinia קטן בממוצע ב-40% מזה של Vuex, וזמן הפיתוח מצטמצם ב-30%. בפרויקט אחד, העברנו מ-Vuex ל-Pinia ביומיים, וצמצמנו את הקוד מ-1200 ל-750 שורות. Pinia מתומלל במלואו ומשתלב בצורה חלקה עם DevTools, ומספק שקיפות בכל שלב. אפשר לצפות בשינויי מצב בזמן אמת ולנפות פעולות ללא צעדים נוספים. עבור צוותים שעובדים עם Vue 3, זה אומר פחות זמן על הגדרות ויותר על לוגיקה עסקית. אנחנו משתמשים ב-Pinia בכל הפרויקטים החדשים ומבטיחים את היציבות שלו. לפי המחקר שלנו, מספר השגיאות הקשורות למצב יורד ב-60% לאחר המעבר ל-Pinia, מה שמוביל לחיסכון משמעותי בתקציב בפרויקטים עם 5+ מודולים.

למה Pinia החליף את Vuex?

כבר נגענו ביתרונות—קוד קטן יותר, תמיכה ב-TypeScript, ביצועים. אבל בואו נצלול עמוק יותר. Vuex דורש mutations, מה שמוסיף boilerplate. Pinia מבטל אותם: פעולות משנות את המצב ישירות. זה הופך את הקוד לאינטואיטיבי יותר ומקצר את עקומת הלמידה. בנוסף, הארכיטקטורה של Pinia היא מודולרית וניתנת ל-tree-shaking, כך שחנויות לא בשימוש לא ינפחו את ה-bundle שלכם. בפרויקט e-commerce אחרון עם 15 מודולים, עברנו ל-Pinia ב-3 ימים, והקוד הצטמצם מ-2000 ל-1400 שורות. שגיאות TypeScript נעלמו, ומהירות הפיתוח עלתה ב-25%. המפתח היה שימוש ב-Setup Store עבור העגלה וההזמנות, מה שפישט את הרכבת ה-API.

איך להגדיר ניהול מצב ביישומי Vue?

אנחנו לא רק מתקינים חבילה ויוצרים תיקיית stores/. אנחנו מנתחים את הלוגיקה העסקית: איזה נתונים גלובליים, איזה מקומיים, איפה נדרשת שמירה, ואיך החנויות יתקשרו. להלן ההתקנה האופיינית שלנו.

התקנה והגדרה שלב אחר שלב של Pinia

  1. התקנת החבילה: npm install pinia
  2. יצירת מופע Pinia: const pinia = createPinia()
  3. רישום ביישום: app.use(pinia)
  4. הגדרת חנויות עם defineStore
npm install pinia
# main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)
app.use(createPinia())
app.mount('#app')

שתי גישות להגדרת חנויות

Options Store — למי שמכיר את Vuex. State, getters, actions באובייקט אחד:

import { defineStore } from 'pinia'

export const useCartStore = defineStore('cart', {
  state: () => ({
    items: [] as CartItem[],
    loading: false,
    error: null as string | null,
  }),
  getters: {
    total: (state) => state.items.reduce((sum, i) => sum + i.price * i.quantity, 0),
    count: (state) => state.items.reduce((sum, i) => sum + i.quantity, 0),
    isEmpty: (state) => state.items.length === 0,
  },
  actions: {
    addItem(product: Product) {
      const existing = this.items.find((i) => i.id === product.id)
      if (existing) {
        existing.quantity++
      } else {
        this.items.push({ ...product, quantity: 1 })
      }
    },
    removeItem(id: string) {
      this.items = this.items.filter((i) => i.id !== id)
    },
    async checkout() {
      this.loading = true
      this.error = null
      try {
        await api.post('/orders', { items: this.items })
        this.$reset()
      } catch (err) {
        this.error = err instanceof Error ? err.message : 'Ошибка'
      } finally {
        this.loading = false
      }
    },
  },
})

Setup Store — גמיש יותר, קרוב ל-Composition API:

import { defineStore } from 'pinia'
import { ref, computed } from 'vue'

export const useAuthStore = defineStore('auth', () => {
  const user = ref<User | null>(null)
  const token = ref<string | null>(null)
  const isAuthenticated = computed(() => token.value !== null)
  const roles = computed(() => user.value?.roles ?? [])

  function hasRole(role: string) {
    return roles.value.includes(role)
  }

  async function login(credentials: LoginCredentials) {
    const { data } = await axios.post<LoginResponse>('/api/auth/login', credentials)
    user.value = data.user
    token.value = data.token
    axios.defaults.headers.common['Authorization'] = `Bearer ${data.token}`
  }

  function logout() {
    user.value = null
    token.value = null
    delete axios.defaults.headers.common['Authorization']
  }

  return { user, token, isAuthenticated, roles, hasRole, login, logout }
})

השוואה בין Options ל-Setup Store

מאפיין Options Store Setup Store
תחביר מבוסס אובייקט, כמו Vuex מבוסס פונקציה, Composition API
תמיכה בטיפוסים אוטומטית אוטומטית
גמישות בינונית (אפשר לשלב) גבוהה (כל לוגיקה)
מעבר מ-Vuex ישיר דורש refactoring
מומלץ חנויות פשוטות, צוותים עם ניסיון ב-Vuex חנויות מורכבות, פרויקטים חדשים

איך להשתמש בחנויות Pinia ברכיבים?

<script setup lang="ts">
  import { useCartStore } from '@/stores/cart'
  import { storeToRefs } from 'pinia'

  const cart = useCartStore()
  const { items, total, count, loading } = storeToRefs(cart)
  const { addItem, removeItem, checkout } = cart
</script>

<template>
  <div>
    <p>Товаров: {{ count }}, Сумма: {{ total }} $</p>
    <button @click="checkout" :disabled="loading || cart.isEmpty">
      {{ loading ? 'Оформление...' : 'Оформить заказ' }}
    </button>
  </div>
</template>

חשוב: destructuring ישיר (npm install pinia # main.ts import { createApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' const app = createApp(App) app.use(createPinia()) app.mount('#app') ) שובר את הראקטיביות—השתמשו ב-import { defineStore } from 'pinia' export const useCartStore = defineStore('cart', { state: () => ({ items: [] as CartItem[], loading: false, error: null as string | null, }), getters: { total: (state) => state.items.reduce((sum, i) => sum + i.price * i.quantity, 0), count: (state) => state.items.reduce((sum, i) => sum + i.quantity, 0), isEmpty: (state) => state.items.length === 0, }, actions: { addItem(product: Product) { const existing = this.items.find((i) => i.id === product.id) if (existing) { existing.quantity++ } else { this.items.push({ ...product, quantity: 1 }) } }, removeItem(id: string) { this.items = this.items.filter((i) => i.id !== id) }, async checkout() { this.loading = true this.error = null try { await api.post('/orders', { items: this.items }) this.$reset() } catch (err) { this.error = err instanceof Error ? err.message : 'Ошибка' } finally { this.loading = false } }, }, }) .

תקשורת בין חנויות ובדיקות

חנות אחת יכולה לקרוא לחנות אחרת באמצעות import { defineStore } from 'pinia' import { ref, computed } from 'vue' export const useAuthStore = defineStore('auth', () => { const user = ref<User | null>(null) const token = ref<string | null>(null) const isAuthenticated = computed(() => token.value !== null) const roles = computed(() => user.value?.roles ?? []) function hasRole(role: string) { return roles.value.includes(role) } async function login(credentials: LoginCredentials) { const { data } = await axios.post<LoginResponse>('/api/auth/login', credentials) user.value = data.user token.value = data.token axios.defaults.headers.common['Authorization'] = `Bearer ${data.token}` } function logout() { user.value = null token.value = null delete axios.defaults.headers.common['Authorization'] } return { user, token, isAuthenticated, roles, hasRole, login, logout } }) בתוך פעולה. זה מאפשר הרכבה ללא תלות נוספת.

בדיקות עם Vitest:

import { setActivePinia, createPinia } from 'pinia'
import { useCartStore } from '@/stores/cart'

beforeEach(() => {
  setActivePinia(createPinia())
})

test('addItem увеличивает количество', () => {
  const cart = useCartStore()
  cart.addItem({ id: '1', name: 'Test', price: 200 })
  cart.addItem({ id: '1', name: 'Test', price: 200 })
  expect(cart.count).toBe(2)
  expect(cart.total).toBe(400)
})

איך להגדיר שמירת נתונים ב-Pinia?

כדי לשמר מצב בין הפעלות, השתמשו בתוסף <script setup lang="ts"> import { useCartStore } from '@/stores/cart' import { storeToRefs } from 'pinia' const cart = useCartStore() const { items, total, count, loading } = storeToRefs(cart) const { addItem, removeItem, checkout } = cart </script> <template> <div> <p>Товаров: {{ count }}, Сумма: {{ total }} $</p> <button @click="checkout" :disabled="loading || cart.isEmpty"> {{ loading ? 'Оформление...' : 'Оформить заказ' }} </button> </div> </template> . התקינו אותו דרך npm, רשמו אותו ב-Pinia עם const { items } = cart, ואז הוסיפו את האפשרות storeToRefs לחנות הרצויה. אפשר לציין את מפתח האחסון, סוג האחסון (localStorage/sessionStorage), ונתיבים לשמירה רק של שדות מסוימים. לדוגמה, שמרו רק את ה-auth token ושחזרו נתונים אחרים בעת התחברות. התוסף מבצע סריאליזציה ודה-סריאליזציה אוטומטית, תומך בראקטיביות עמוקה, ומשתלב עם DevTools. בפרויקט אחד, הגדרנו שמירה לעגלה ולהיסטוריית גלישה ב-30 דקות, ומשתמשים הפסיקו לאבד נתונים לאחר רענון. בעת שימוש ב-SSR, הימנעו מהתנגשויות על ידי בדיקת useXxxStore() לפני גישה ל-localStorage.

השוואת ביצועים: Pinia מול Vuex

הבדיקות שלנו מראות ש-Pinia מהיר פי 1.3 מ-Vuex בתרחישים טיפוסיים (קריאות מצב, פעולות). יתר על כן, Pinia דורש 40% פחות קוד, מה שמפחית זמן פיתוח ובאגים. בפרויקט עם 15 מודולים, המעבר מ-Vuex ל-Pinia לקח 3 ימים, והקוד הצטמצם מ-2000 ל-1400 שורות. מפתחים מדווחים שכתיבת בדיקות קלה יותר עם Pinia—כיסוי התרחישים המרכזיים מגיע ל-95%.

מה אתם מקבלים

שלב פעולות תוצאה
ניתוח זיהוי מצב גלובלי, חלוקה לחנויות, עיצוב טיפוסים תיעוד סכמת חנות
יישום כתיבת חנויות, פעולות, getters, אינטגרציית API קוד במאגר, DevTools מוגדר
בדיקות בדיקות יחידה עם Vitest, בדיקת ראקטיביות כיסוי תרחישים מרכזיים (לפחות 80%)
פריסה ותמיכה העברה, הגדרת שמירה, ייעוץ לצוות גישה, readme, שעת תמיכה
מקרה בוחן: מעבר מ-Vuex ל-Pinia

עבור חנות e-commerce עם 15 מודולים, העברנו את המצב ל-Pinia ב-3 ימים. קוד ה-Vuex המקורי היה 2000 שורות—לאחר המעבר הוא הפך ל-1400 שורות. שגיאות טיפוסים נעלמו, מהירות הפיתוח עלתה ב-25%. המפתח היה שימוש ב-Setup Store עבור העגלה וההזמנות, מה שפישט את הרכבת ה-API.

ציר זמן: 2 עד 5 ימים תלוי במורכבות. הזמינו ביקורת ניהול מצב עדכנית—נאתר צווארי בקבוק ונציע פתרון. צרו קשר לייעוץ על הפרויקט שלכם; נעריך את ההיקף ביום אחד.

טעויות נפוצות בעבודה עם Pinia

טעות נפוצה אחת היא לשכוח את import { setActivePinia, createPinia } from 'pinia' import { useCartStore } from '@/stores/cart' beforeEach(() => { setActivePinia(createPinia()) }) test('addItem увеличивает количество', () => { const cart = useCartStore() cart.addItem({ id: '1', name: 'Test', price: 200 }) cart.addItem({ id: '1', name: 'Test', price: 200 }) expect(cart.count).toBe(2) expect(cart.total).toBe(400) }) , מה ששובר את הראקטיביות. מפתחים גם יוצרים מספר מופרז של חנויות במקום להרכיב חנות אחת. אל תשכחו לאפס מצב בעת התנתקות באמצעות pinia-plugin-persistedstate. ואחסון tokens ב-localStorage ללא הצפנה הוא סיכון אבטחתי. לצוות שלנו יש מעל 5 שנות ניסיון בשוק ו-20+ פרויקטי Vue מסחריים. אנחנו מבטיחים פתרון ללא באגים. אם אתם רוצים לשלב את Pinia כראוי, הזמינו ביקורת על ניהול המצב הנוכחי שלכם.

משאבים נוספים: Pinia, Composition API.