Я не могу заставить несколько компонентов, обращающихся к одному и тому же хранилищу, реагировать на обновления, пока я не запутаюсь с элементом dom, чтобы вызвать новый рендеринг.
В моем магазине Pinia у меня есть массив и метод обновления:
let MyArray: IMyItem[] = [
{ id: 1,
name: "First Item",
}, ....
let SelectedItem = MyArray[0]
const AddItem = ( n: string, ) => {
MyArray.push({ id: createId(), name: n, });
};
return { MyArray, SelectedItem, AddItem }
В одном компоненте Vue у меня есть ввод текста и кнопка для вызова метода хранилища:
function handle() {store.AddItem(name.value));
В другом компоненте Vue для того же родителя я использую цикл for для отображения возможности выбора элемента:
<div v-for = "item in store.MyArray">
<input type = "radio"...
Никаких изменений с этими усилиями:
const { MyArray } = storeToRefs(store);
const myArray = reactive(store.MyArray);
// also watching from both components...
watch(store.MyArray, (n, o) => console.dir(n));
// also... lots of other stuff.
const myArray = reactive(store.MyArray);
watch(myArray, (n, o) => console.dir(n));
Я также экспериментировал с <form @submit.prevent = "handle">
запуском nextTick
, добавляя возврат строки в метод хранилища.
Я предполагаю, что причина, по которой щелчок вокруг заставляет его работать, заключается в том, что я меняю магазин SelectedItem
, и его реактивность требует повторного рендеринга, как это v-model
для ярлыка.
В документах говорится, что Array.push должен выполнять свою работу... просто он не связан таким же образом при использовании в v-for
.
Что необходимо для запуска обновления dom? Спасибо! ?
не могли бы вы показать свой магазин пиния
Верхний блок кода — это магазин. Он предоставляет 3 вещи: функцию MyArray, SelectedItem и AddItem.
let MyArray: IMyItem[] = [
- это не реактивно, это ошибка. const myArray = reactive(store.MyArray)
- не имеет смысла, потому что store.MyArray уже должен быть реактивным в этот момент
Как указывалось в комментариях, основная проблема заключается в том, что состояние вашего магазина не объявлено с помощью API Reactivity, поэтому изменения состояния не вызовут срабатывания наблюдателей и не вызовут повторную визуализацию.
Решение состоит в том, чтобы объявить MyArray
как reactive
и SelectedItem
как ref
:
// store.js
import { defineStore } from 'pinia'
import type { IMyItem } from './types'
import { createId } from './utils'
? ?
import { ref, reactive } from 'vue'
export const useItemStore = defineStore('item', () => {
?
let MyArray = reactive([{ id: createId(), name: 'First Item' }] as IMyItem[])
?
let SelectedItem = ref(MyArray[0])
const AddItem = (n: string) => {
MyArray.push({ id: createId(), name: n })
}
return { MyArray, SelectedItem, AddItem }
})
Если вы используете storeToRefs()
, обязательно установите свойство ref
.value
при обновлении SelectedItem
:
// MyComponent.vue
const store = useItemStore()
const { SelectedItem, MyArray } = storeToRefs(store)
const selectItem = (id) => {
?
SelectedItem.value = MyArray.value.find((item) => item.id === id)
}
Но в этом случае проще использовать реквизиты напрямую из store
:
// MyComponent.vue
const store = useItemStore()
const selectItem = (id) => {
store.SelectedItem = store.MyArray.find((item) => item.id === id)
}
В компоненте, который должен обновляться, определите вычисляемое свойство, которое просто возвращает значение хранилища, и используйте вычисляемое свойство для рендеринга вашего шаблона.