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 шт):

Автор решения: vova

Для вызова метода добавления, надо было использовать не myList:

  setup() {
    const reactiveMyList = reactive<MyList>(myList);
    const handleAdd = () => myList.add();
    ...

а reactiveMyList:

const handleAdd = () => reactiveMyList.add();

Не думал, что можно обращаться как к проксированным свойствам, так и к исходным. Вот такой нюанс.

→ Ссылка