Как подключить изменяемый объект к неизменяемому объекту reacitve?

У нас есть составная функция useApplicationPreferences(), используемая в Vue 2 с Composition API. Эта функция предоставляет вычисленный не записываемый ref с именем darkMode:

//useApplicationPreferences.ts
import { reactive, computed } from '@vue/composition-api'
import { Dark } from 'quasar'

const defaultState = () => ({
  preference: {
    darkMode: true,
  },
})

const state = reactive(defaultState())

export const useApplicationPreferences = () => {
  const setPreference = async (
    preference: {
      darkMode?: boolean
    }
  ) => {
    if (preference.darkMode != null) {
      Dark.set(preference.darkMode)
      state.preference.darkMode = preference.darkMode
    }
  }

  return {
    darkMode: computed(() => state.preference.darkMode),
    setPreference,
  }
}

Мы успешно используем эту функцию в другой части приложения сразу после входа пользователя в систему. Это позволяет получить настройки из серверной части и установить их в приложении. Проблема, с которой мы столкнулись, находится на другой странице, где у нас есть кнопка переключения с `v-model = darkModeToggle.

// Settings.vue
import { defineComponent, ref, watch } from '@vue/composition-api'
import { useApplicationPreferences } from './useApplicationPreferences'

export default defineComponent({
  setup() {
    const { darkMode, setPreference } = useApplicationPreferences()
    const darkModeToggle = ref(darkMode.value)

    watch(
      () => darkModeToggle.value,
      async (newValue) => {
        await setPreference({ darkMode: newValue }, { saveToBackend: true })
      }
    )

    return {
      darkModeToggle,
    }
  },
})

Как можно подключить darkMode из составного объекта к darkModeToggle ref в шаблоне Settings.vue? Вычисленное свойство darkMode недоступно для записи. но переключатель должен использовать его как значение и иметь возможность изменять его значение, вызывая setPreference().

Спасибо за помощь.


person DarkLite1    schedule 09.12.2020    source источник


Ответы (2)


Я думаю, у вас есть три варианта, и вы должны выбрать тот, который соответствует вашему стилю.

1. Сделайте ссылку доступной для записи.

Это самый простой способ, и я думаю, вы ошибаетесь. Вы создаете составной объект, которому разрешено напрямую читать ref через computed , но ваши намерения противоположны. Вы действительно хотите, чтобы открытая ссылка была доступна для записи всем, у кого есть доступ к (v-model).

2. Используйте вычисленное значение get / set.

Это вариант, но он не сильно отличается от открытого ref. https://composition-api.vuejs.org/api.html#computed

const state = reactive({ on: false })

const myComputed = computed({
  get () {
    return state.on
  },

  set (value) {
    state.on = value
  }
})

3. Уничтожьте директиву v-model.

Вы можете деструктурировать директиву v-model на привязку value и событие input. Пример:

<Toggle :value="myComputed" @input="setPreference" />

https://vuejs.org/v2/guide/components.html#Using-v-model-on-Components

person Alex29    schedule 09.12.2020

Чувствую себя здесь немного глупо. Сразу после публикации вопроса я нашел вариант get и set свойства computed в Документы Vue:

export default defineComponent({
  setup() {
    const { darkMode, setPreference } = useApplicationPreferences()

    const darkModeToggle = computed({
      get: () => {
        return darkMode.value
      },
      set: async (val) => {
        await setPreference({ darkMode: val })
      },
    })
person DarkLite1    schedule 09.12.2020
comment
Ой, я не видел твоего ответа. Во всяком случае, в своем ответе я дал вам другие решения вашей проблемы. Надеюсь, это поможет. Между прочим, я не знаю, хорошая ли идея создать записываемый компьютер, вычисляемый с помощью асинхронной функции. Это возможно, но ради вашего психического здоровья я бы избегал таких вещей, потому что это может привести к нежелательным последствиям. - person Alex29; 09.12.2020