VueJs передача аргумента инлайново

Привет! Есть простейший кусок кода Vue3:

<script setup>
import { reactive, ref } from 'vue'

const isActive = ref(false)

function toggle(state) {
  state.value = !state.value
}
</script>

<template>
  <button @click="toggle(isActive)">Нажми меня</button>
  Состояние: <strong>{{ isActive }}</strong>
</template>

Постоянно получаю ошибку:
Cannot create property ‘value’ on boolean ‘false’
Да, я понял, что при подстановку в шаблон Vue разворачивает прокси и подставляет в обработчик клика не сам реактивный объект, а его булево значение. Но как тогда сохранить реактивность? Если в toggle вписать state = !state - ошибок нет, но и ничего не меняется.
Кто разбирается в этом?

Приветствия.

Он обычно разворачивает ref-ы только в шаблонах. Я не силен в его теории, но проверил вручную и через ии.

Мне думается что isActive в шаблоне и развернулся в булевое, уже булевое было передано аргументом, и райнтайм ошибка происходит из-за попытки создать/доступиться к свойству .value (скорее всего это ожидаемое свойство или геттер/setter ref-а, куда пишется значением) в булевом типе данных. Можно проверить на Ref-ность значение в state внутри toggle с помошью isRef(state). А еще лучше так просто посмотри на точный тип данных в переменной state.

Скорее всего если не передавать state аргументом, и менять значение напрямую из тела функции, то все сработает.

Вот для примера два варианта с логгированием. Один - твой оригинальный. Второй - мой как рекомендую поправить Vue 3 App

Привет! Да, всё оказалось так: в ref это всё разворачивается в обычные значения… Проблема была в том, что эта функция - одна и та же - должна была тупо инвертировать false->true-> разных флагов, поэтому вариант управления переменной из тела не подходил. Но принцип я нашёл такой: нужны старые добрые замыкания и запуск функции в (я использовал SFC Composition API), а в шаблоне - только имя функции. В итоге получилось так:

<script setup>
import { reactive, ref } from 'vue'

const isActive = ref(false)

function toggle(state) {
  return function () {
    state.value = !state.value
  }
}

const toggleActive = toggle(isActive)
</script>

<template>
  <button @click="toggleActive">Нажми меня</button>
  Состояние: <strong>{{ isActive }}</strong>
</template>

И всё заработало… Теперь можно передавать разные булевы флаги в эту функцию и всё будет работать. Спасибо за внимание к вопросу :)

1 лайк