首页 > web前端 > js教程 > 正文

了解 Vue 与 Pinia Store 的反应性

Barbara Streisand
发布: 2024-11-20 15:51:14
原创
564 人浏览过

Understanding Vue Reactivity with Pinia Stores

在我的工作场所,我的任务是为内部本地开发工作创建一个模拟聊天商店,在这样做的同时,我做了一些关于 Vue 的笔记(我有一些经验,但没有hooks),所以这只是我的黑曜石笔记,希望对你有用:)

目录

  1. 参考和反应参考
  2. 观看和反应
  3. Pinia 商店集成
  4. 实际例子
  5. 最佳实践
  6. 常见问题

参考文献和反应参考文献

什么是参考?

ref 是 Vue 使原始值具有响应性的方式。它将值包装在带有 .value 属性的响应式对象中。

import { ref } from 'vue'

// Inside Pinia Store
export const useMyStore = defineStore('my-store', () => {
  // Creates a reactive reference
  const count = ref<number>(0)

  // To access or modify:
  function increment() {
    count.value++  // Need .value for refs
  }

  return {
    count,  // When exposed, components can use it without .value
    increment
  }
})
登录后复制

商店中的参考文献类型

// Simple ref
const isLoading = ref<boolean>(false)

// Array ref
const messages = ref<Message[]>([])

// Complex object ref
const currentUser = ref<User | null>(null)

// Ref with undefined
const selectedId = ref<string | undefined>(undefined)
登录后复制

观察和反应

手表的基本使用

import { watch, ref } from 'vue'

export const useMyStore = defineStore('my-store', () => {
  const messages = ref<Message[]>([])

  // Simple watch
  watch(messages, (newMessages, oldMessages) => {
    console.log('Messages changed:', newMessages)
  })
})
登录后复制

观看选项

// Immediate execution
watch(messages, (newMessages) => {
  // This runs immediately and on changes
}, { immediate: true })

// Deep watching
watch(messages, (newMessages) => {
  // Detects deep object changes
}, { deep: true })

// Multiple sources
watch(
  [messages, selectedId], 
  ([newMessages, newId], [oldMessages, oldId]) => {
    // Triggers when either changes
  }
)
登录后复制

Pinia 商店集成

带有引用的存储结构

export const useMyStore = defineStore('my-store', () => {
  // State
  const items = ref<Item[]>([])
  const isLoading = ref(false)
  const error = ref<Error | null>(null)

  // Computed
  const itemCount = computed(() => items.value.length)

  // Actions
  const fetchItems = async () => {
    isLoading.value = true
    try {
      items.value = await api.getItems()
    } catch (e) {
      error.value = e as Error
    } finally {
      isLoading.value = false
    }
  }

  return {
    items,
    isLoading,
    error,
    itemCount,
    fetchItems
  }
})
登录后复制

组合商店

export const useMainStore = defineStore('main-store', () => {
  // Using another store
  const otherStore = useOtherStore()

  // Watching other store's state
  watch(
    () => otherStore.someState,
    (newValue) => {
      // React to other store's changes
    }
  )
})
登录后复制

实际例子

自动刷新实现

export const useChatStore = defineStore('chat-store', () => {
  const messages = ref<Message[]>([])
  const refreshInterval = ref<number | null>(null)
  const isRefreshing = ref(false)

  // Watch for auto-refresh state
  watch(isRefreshing, (shouldRefresh) => {
    if (shouldRefresh) {
      startAutoRefresh()
    } else {
      stopAutoRefresh()
    }
  })

  const startAutoRefresh = () => {
    refreshInterval.value = window.setInterval(() => {
      fetchNewMessages()
    }, 5000)
  }

  const stopAutoRefresh = () => {
    if (refreshInterval.value) {
      clearInterval(refreshInterval.value)
      refreshInterval.value = null
    }
  }

  return {
    messages,
    isRefreshing,
    startAutoRefresh,
    stopAutoRefresh
  }
})
登录后复制

加载状态管理

export const useDataStore = defineStore('data-store', () => {
  const data = ref<Data[]>([])
  const isLoading = ref(false)
  const error = ref<Error | null>(null)

  // Watch loading state for side effects
  watch(isLoading, (loading) => {
    if (loading) {
      // Show loading indicator
    } else {
      // Hide loading indicator
    }
  })

  // Watch for errors
  watch(error, (newError) => {
    if (newError) {
      // Handle error (show notification, etc.)
    }
  })
})
登录后复制

最佳实践

1. 参考初始化

// ❌ Bad
const data = ref()  // Type is 'any'

// ✅ Good
const data = ref<string[]>([])  // Explicitly typed
登录后复制

2. 观察清理

// ❌ Bad - No cleanup
watch(source, () => {
  const timer = setInterval(() => {}, 1000)
})

// ✅ Good - With cleanup
watch(source, () => {
  const timer = setInterval(() => {}, 1000)
  return () => clearInterval(timer)  // Cleanup function
})
登录后复制

3. 计算与观看

// ❌ Bad - Using watch for derived state
watch(items, (newItems) => {
  itemCount.value = newItems.length
})

// ✅ Good - Using computed for derived state
const itemCount = computed(() => items.value.length)
登录后复制

4. 店铺组织

// ✅ Good store organization
export const useStore = defineStore('store', () => {
  // State refs
  const data = ref<Data[]>([])
  const isLoading = ref(false)

  // Computed properties
  const isEmpty = computed(() => data.value.length === 0)

  // Watchers
  watch(data, () => {
    // Handle data changes
  })

  // Actions
  const fetchData = async () => {
    // Implementation
  }

  // Return public interface
  return {
    data,
    isLoading,
    isEmpty,
    fetchData
  }
})
登录后复制

常见问题

  1. 忘记.value
// ❌ Bad
const count = ref(0)
count++ // Won't work

// ✅ Good
count.value++
登录后复制
  1. 观看时间
// ❌ Bad - Might miss initial state
watch(source, () => {})

// ✅ Good - Catches initial state
watch(source, () => {}, { immediate: true })
登录后复制
  1. 内存泄漏
// ❌ Bad - No cleanup
const store = useStore()
setInterval(() => {
  store.refresh()
}, 1000)

// ✅ Good - With cleanup
const intervalId = setInterval(() => {
  store.refresh()
}, 1000)
onBeforeUnmount(() => clearInterval(intervalId))
登录后复制

记住:在 Pinia 商店

与裁判和手表合作时,请始终考虑清理、类型安全和适当的组织

以上是了解 Vue 与 Pinia Store 的反应性的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板