Vue 3 - не работает реактивность массива в объекте
Есть простенький класс MyList
export class MyList {
public items: string[] = [];
public add(): void {
this.items.push(`value ${this.items.length}`);
}
}
export const myList = new MyList();
Делаю экземпляр этого класса реактивным, и ожидаю, что изменения будут отображаться в шаблоне.
<template>
<p>myList.items.length={{ reactiveMyList.items.length }}</p>
<button @click="handleAdd">Add</button>
</template>
<script lang="ts">
import { defineComponent, reactive } from 'vue';
import { myList, MyList } from '@/MyList';
export default defineComponent({
setup() {
const reactiveMyList = reactive<MyList>(myList);
const handleAdd = () => myList.add();
return { reactiveMyList, handleAdd };
},
});
</script>
Но по нажатию кнопки, ничего не происходит. Вроде во втором такие конструкции всегда работали...
Поэкспериментировав, обнаружил, что, если добавить реактивность в сам класс, то все работает.
export class MyList {
public items: string[] = reactive([]);
...
Но, если же по аналогии переписать компонент:
<template>
<p>items.length={{ items.length }}</p>
<button @click="handleOk">Ok</button>
</template>
...
setup() {
const items = reactive<string[]>(myList.items);
const handleOk = () => myList.add();
return { items, handleOk };
},
То шаблон вновь не реагирует на изменения, почему?
Причем, если механизм реактивности задействован локально, то все хорошо:
setup() {
const itemsLocal = reactive<string[]>([]);
const handleOk = () => itemsLocal.push(`value ${itemsLocal.length}`);
...
<template>
<p>items.length={{ items.length }}</p>
<p>itemsLocal.length={{ itemsLocal.length }}</p>
...
Значит сбой вносит именно объектность, но как с этим бороться?
(ещё через 2 часа...) Ооо... скоро на стену полезу... Добавил в нажатие кнопки увеличение и локального массива и объектного:
const handleOk = () => {
myList.add();
itemsLocal.push(`value ${itemsLocal.length}`);
};
И ОБА работают! Убираю увеличение локального и вновь тишина... Ну так же не должно быть!
Ответы (1 шт):
Для вызова метода добавления, надо было использовать не myList:
setup() {
const reactiveMyList = reactive<MyList>(myList);
const handleAdd = () => myList.add();
...
а reactiveMyList:
const handleAdd = () => reactiveMyList.add();
Не думал, что можно обращаться как к проксированным свойствам, так и к исходным. Вот такой нюанс.