Двухстороннее связывание данных с: model.sync, когда prop имеет get () и set () - PullRequest
0 голосов
/ 25 октября 2018

У меня есть вычисляемое свойство, которое я использую как v-model на входе.Я написал это таким образом, чтобы получить реактивность - это вызывает мое setText действие Vuex, которое я затем могу получить с помощью своего геттера text.Это выглядит так:

text: {
   get() {
     return this.text;
   },
   set(value) {
     this.setText(value);
   },
 },

, и я использую его в своем вводе так:

<input class="input" type="text" v-model="text" />

Это хорошо работает.Теперь я поместил рассматриваемый input в отдельный компонент, который я использую.Это означает, что я должен передать text v-модель в качестве реквизита, что я делаю с :model.sync, вот так:

<myInput :model.sync="text"/>

и в myInput компонент Iиспользуйте реквизиты так:

<input class="input" id="search-order" type="text" :value="model" @input="$emit('update:model', $event)">

Но, похоже, это не работает вообще, когда я набираю данные на входе, на входе появляется сообщение: [object InputEvent], и если я пытаюсь увидеть и значениеmodel это {isTrusted: true}.Я предполагаю, что это из-за геттеров и сеттеров, которые есть в моем вычисленном свойстве.Как передать их дочернему компоненту?

1 Ответ

0 голосов
/ 25 октября 2018

Вместо использования модификатора .sync вы можете поддерживать директиву v-model в своем пользовательском компоненте.v-model - это синтаксический сахар для value prop и input события.

Для поддержки v-model просто убедитесь, что ваш пользовательский компонент имеет value prop и генерирует событие input сновое значение: this.$emit('input', event.target.value).

Вот пример компонента <BaseInput>, который я использую, он написан на TypeScript:

<template>
  <input
    :type="type"
    :value="value"
    class="input"
    v-on="listeners"
  >
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  name: 'BaseInput',

  props: {
    type: {
      type: String,
      default: 'text',
    },

    value: {
      type: [String, Number],
      default: '',
    },

    lazy: {
      type: Boolean,
      default: false,
    },

    number: {
      type: Boolean,
      default: false,
    },

    trim: {
      type: Boolean,
      default: false,
    },
  },

  computed: {
    modelEvent(): string {
      return this.lazy ? 'change' : 'input'
    },

    parseModel(): (value: string) => string | number {
      return (value: string) => {
        if (this.type === 'number' || this.number) {
          const res = Number.parseFloat(value)
          // If the value cannot be parsed with parseFloat(),
          // then the original value is returned.
          return Number.isNaN(res) ? value : res
        } else if (this.trim) {
          return value.trim()
        }
        return value
      }
    },

    listeners(): Record<string, Function | Function[]> {
      return {
        ...this.$listeners,
        [this.modelEvent]: (event: HTMLElementEvent<HTMLInputElement>) =>
          this.$emit(this.modelEvent, this.parseModel(event.target.value)),
      }
  },
})
</script>

Вы можете использовать его так:

<BaseInput v-model="text" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...