Реактивный объект в Vue 3 Composition API не обновляется с помощью события @click

Мне кажется, что в Vue Composition API чего-то не хватает, когда дело доходит до использования и обновления реактивных объектов.

См. Код ниже. Я ожидаю, что событие щелчка обновит вывод {{colors}} в шаблоне при добавлении цвета.

<template>
  <div>
    <!-- {{colors}} Is not updated in the DOM on click event -->
    <pre>{{ colors }}</pre>
    <button @click="addColor">add color</button>
  </div>
</template>

<script>
import { reactive } from 'vue';

export default {
  setup() {
    let colors = reactive({ green: '#ccc000' });

    function addColor() {
      // By cloning and creating a new merged object
      colors = Object.assign({}, colors, { red: '#fff000' });
      // Or by changing the object directly
      colors.orange = '#322332'; // Also does not work
      console.log(colors); // Logs out the correct value
    }

    return {
      colors,
      addColor,
    };
  },
};
</script>

В журнале консоли я вижу, что значение цветов обновляется, но не в DOM.

Вот песочница кода

https://codesandbox.io/s/mystifying-roentgen-rox9k?file=/src/App.vue


person AndyJamesN    schedule 09.06.2021    source источник


Ответы (1)


Вероятно, вам не стоит создавать новый объект:

colors = Object.assign({}, colors, { red: '#fff000' });

Вместо этого попробуйте манипулировать существующим объектом:

delete colors.green;
colors.red = '#fff000';
person obe    schedule 09.06.2021
comment
Я фактически обновил свой пример немного ранее, показывая именно то, что вы предложили, поскольку он также не работает. изменить: я удалил строку назначения объекта, и она работает - person AndyJamesN; 09.06.2021
comment
Вместо colors = Object.assign(), а не в дополнение. - person obe; 09.06.2021
comment
@AndyJamesN Вы заменили реактивный прокси на обычный объект. Вот почему он не реагировал, когда вы манипулировали им напрямую. - person Husam Ibrahim; 09.06.2021
comment
и, кстати, более крутой синтаксис для colors = Object.assign... был бы colors = { ...colors, red: '#fff000' } :) - person obe; 09.06.2021
comment
Да, в этом есть смысл! Перед назначением объекта я использовал оператор распространения для слияния, но, поскольку ничего не работало, я пробовал разные вещи. К сожалению, это все еще не работает в моем коде. Я использую Nuxt с API композиции '' @ nuxtjs / Composition-api 'и, как ни странно, тот же код, который работает в codeandbox с вашими предложениями в vue, не работает в моей сборке Nuxt. - person AndyJamesN; 09.06.2021
comment
@AndyJamesN Это использует плагин API композиции для Vue 2, поэтому полагается на старую систему реактивности (т.е. не использует прокси). Следовательно, он будет страдать от тех же проблем с реактивностью. - person Husam Ibrahim; 09.06.2021
comment
Вот песочница с использованием nuxt codeandbox.io/s/ - person AndyJamesN; 09.06.2021
comment
@HusamIbrahim Ну, это бы все объяснило. На странице Nuxt Composition-api.nuxtjs.org написано, что Vue 3 Composition API Получить все Composition API функции Nuxt 2. Думаю, это связано с некоторыми не столь очевидными оговорками. - person AndyJamesN; 09.06.2021
comment
В качестве обходного пути я собираюсь использовать вместо этого хранилище Vuex. Это позволит мне редактировать мой основной цветной объект (который на самом деле намного сложнее, чем просто цвета) по мере необходимости и использовать вычисленные, чтобы вещи оставались реактивными. Спасибо всем за отзывы. - person AndyJamesN; 09.06.2021