(Vue.js) V-модель массива.С трудом работает функция - PullRequest
0 голосов
/ 11 мая 2019

Я работаю с портфельным проектом, где пользователи могут загрузить изображение, предоставить описание под ним, а затем нажать кнопку «Добавить», чтобы добавить другое изображение и описание.

Я пытаюсь добавить счетчик символов для ввода описания, которое является полем textarea. Обычно я могу добавить имя v-model в функцию, и она отлично работает, но этот textarea находится в for -цикле, поэтому я не уверен, как заставить эту функцию работать.

Шаблон:

<div class="newPortfolioList">
    <div class="newPortfolioItem" v-for="(item, index) in this.portfolioItems" v-bind:key="index">
....
       <div class="newPortfolioDescription">
          <textarea v-model="item.portfolioDescription" @keyup='remaincharCount()' maxlength="1000" placeholder="Item Description..."></textarea>
       </div>

       <!--  Displaying the remaining characters -->
       <span style="text-align:left; padding: 10px;">{{ remaincharactersText }}</span>
    </div>
...         

Сценарий:

export default {
    data () {
        return {
            portfolioItems:[],
            maxcharacter: 1000,
            remaincharactersText: "1000 characters remaining"            
        }
    },
    methods: {
        createPortfolioItem () {
            this.portfolioItems.push({
                portfolioDescription: ''
            })
        },
        remaincharCount () {
            if (this.foo.length > this.maxcharacter) {
              this.remaincharactersText = "Exceeded "+this.maxcharacter+" characters limit.";
            } else {
              var remainCharacters = this.maxcharacter - this.foo.length;
              this.remaincharactersText = remainCharacters + " characters remaining";
            }
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 12 мая 2019

Есть несколько способов сделать это.

В этом случае, я думаю, ваш лучший вариант - ввести новый компонент для представления одного элемента портфеля. Каждый из этих компонентов может управлять своим собственным сообщением. С их точки зрения, нет цикла для рассмотрения.

Таким образом, у вас будет что-то вроде этого для шаблона списка:

<div class="newPortfolioList">
    <my-new-portfolio-item
        v-for="(item, index) in portfolioItems"
        :key="index"
        :portfolio-item="item"
    />
</div>

Два примечания. Я удалил префикс v-bind на вашем ключе, достаточно :. Я также удалил this. до portfolioItems, поскольку это также не нужно. Правила Vue Linting могут быть использованы для контроля этих вещей.

Существуют альтернативы внедрению нового компонента. Вы можете сгенерировать значение remaincharactersText в шаблоне, а не сохранять его в состоянии. Это может быть вызов метода, но он не будет рассчитан заранее Примерно так:

<span style="text-align:left; padding: 10px;">{{ remaincharCount(item) }}</span>

Еще одна (еще более болезненная) альтернатива - сделать remaincharactersText массивом значений, а затем получить соответствующее значение по индексу:

<span style="text-align:left; padding: 10px;">{{ remaincharactersText[index] }}</span>

Но, повторюсь, введение отдельного компонента для элементов в v-for, вероятно, является лучшим путем.

1 голос
/ 12 мая 2019

Вы должны знать, что текстовое поле уже имеет maxlength, установленное на 1000, поэтому метка Exceeded N characters limit невозможна (если вы не проверили менее 1000).В настоящее время на ярлыке всегда будет отображаться N reminaing characters.

Вариант 1: Отображать подсчет подсчета в строке

Вместо сохранения количества знаков (излишне занимая дополнительную память), вы можете отобразить вычисление в строкес интерполяцией строк:

<template>
  <div>
    <textarea v-model="item.portfolioDescription" maxlength="1000"></textarea>
    <span>{{ 1000 - item.portfolioDescription.length }} remaining characters</span>
  </div>
</template>

демо 1

Вариант 2: Отображать счетчик из переменной элемента

Если вы предпочитаете сохранять количество символов (например,(для некоторой внутренней обработки), вы можете добавить новое свойство к данным элемента:

<script>
const MAXLEN = 1000

export default {
  methods: {
    createPortfolioItem() {
      this.portfolioItems.push({
        remainChars: MAXLEN, // <--
      })
    },
  }
}
</script>

Затем обновите item.remainChars после textarea input -событие и отображение item.remainChars inline.

<template>
  <div>
    <textarea v-model="item.portfolioDescription" maxlength="1000"
              @input="item.remainChars = 1000 - item.portfolioDescription.length">
    </textarea>
    <span>{{ item.remainChars }} remaining characters</span>
  </div>
</template>

demo 2

Опция 3: Показать вычисленный текст

Вы можете вычислить меток с количеством символов в отдельном массиве, который соответствует portfolioItems:

<script>
const MAXLEN = 1000

export default {
  computed: {
    remainingCharsText() {
      return this.portfolioItems.map(item => `${MAXLEN - item.portfolioDescription.length} remaining characters`)
    },
  }
}
</script>

Затем обновите ваш шаблон, чтобы он ссылался на этот вычисленный массив: index:

<template>
  <div>
    <textarea v-model="item.portfolioDescription" maxlength="1000">
    </textarea>
    <span>{{ remainingCharsText[index] }}</span>
  </div>
</template>

демо 3

...