Vue2: использовать компонент формы с текстовым полем типа ввода для отображения и редактирования данных (без прямого управления реквизитами)

Я создаю MVP и впервые занимаюсь веб-разработкой. Я использую Vue2 и Firebase, и пока все идет хорошо.

Однако я столкнулся с проблемой, которую не могу решить в одиночку. У меня есть представление о том, как это ДОЛЖНО работать, но я не могу записать это в код, и надеюсь, что вы, ребята, поможете мне распутать мои мысли. К настоящему времени я невероятно сбит с толку и все больше разочарован: D

Итак, давайте посмотрим, что у меня получилось:

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

<template>
  <div class="wrap">
    <form class="form">
    
      <p class="label">Headline</p>
      <textarea rows="2" 
      v-model="propHeadline" 
      :readonly="readonly">
      </textarea>
      
      // To switch between read and edit
      <button
        v-if="readonly"
        @click.prevent="togglemode()">
        edit
      </button>
      <button
        v-else
        type="submit"
        @click.prevent="togglemode(), updatePost()"
      >
        save
      </button>
    </form>
  </div>
</template>

<script>
export default {
name: 'PostComponent'
  data() {
    return {
      readonly: true
    }
  },

  props: {
    propHeadline: {
      type: String,
      required: true
    }
  },
  
  methods: {
    togglemode() {
      if (this.readonly) {
        this.readonly = false
      } else {
        this.readonly = true
      }
    },
    updatePost() {
      // updates it to the API - that works
    }
  }
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
And my parent component:

<template>
  <div class="wrap">
      <PostComponent
        v-for="post in posts"
        :key="post.id"
        :knugHeadline="post.headline"
      />
  </div>
</template>

<script>
import PostComponent from '@/components/PostComponent.vue'

export default {
  components: { PostComponent },
  data() {
    return {
      posts: []
    }
  },
  created() {
    // Gets all posts from DB and pushes them in array "posts"
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

Текущий статус Пока все работает. Я могу отображать все сообщения, а при нажатии на редактировать я могу вносить изменения и сохранять их. Все обновляется до Firebase - отлично!

Сообщение о проблеме / ошибке Я получаю следующее сообщение об ошибке:

[Предупреждение Vue]: избегайте изменения свойства напрямую, так как значение будет перезаписано при повторной визуализации родительского компонента. Вместо этого используйте данные или вычисленное свойство на основе значения свойства.

Как говорится в ошибке, я должен использовать вычисляемое свойство на основе значения props. Но как я могу этого добиться?

Подход к решению. Я считаю, что мне нужно использовать вычисляемый метод получения, чтобы вернуть значение свойства. Как это сделать?

И затем я должен использовать сеттер для отправки события родительскому элементу, чтобы обновить значение, чтобы опора вернула его обратно - как это сделать?

Я нашел обрывки в Интернете, но сейчас все, что я вижу, - это счастливые семьи, которые обмениваются небольшими пакетами данных ...

Был бы очень благодарен за предложение, как решить эту проблему! :)

Большое спасибо!


person knugget    schedule 06.11.2020    source источник


Ответы (1)


Эта ошибка возникает из-за вашего v-model в texterea, который изменяет свойство, но в vue запрещено изменять свойства:

<textarea rows="2" 
  v-model="propHeadline" 
  :readonly="readonly">
  </textarea>

Итак, что вы могли бы сделать, это использовать этот created() хук жизненного цикла и установить propHeadline опору как данные:

<script>
export default {
name: 'PostComponent'
  data() {
    return {
      readonly: true,
      headline: ""
    }
  },

  props: {
    propHeadline: {
      type: String,
      required: true
    }
  },
  
  created() {
     this.headline = this.propHeadline
  }
}
</script>

Затем обновите новую переменную в текстовом поле:

<textarea rows="2" 
  v-model="headline" 
  :readonly="readonly">
  </textarea>
person Esteban MANSART    schedule 06.11.2020
comment
О, чувак, жизнь может быть такой простой, когда ты знаешь, что делаешь: D Работает как шарм, большое спасибо! - person knugget; 06.11.2020