JSFiddle - React, Tailwind, and code Playground

HTML

<script src="https://unpkg.com/vue"></script>
<section id="app">
  <content-editor></content-editor>
</section>

<template id="content-list-template">
  <section class="content-list">
    <div v-for="(currentView, index) in views">
      <component :is="currentView.type" :model="currentView.model" :update="updateContent(index)"></component>
      <a v-on:click="removeContent(index)">Remove</a>
    </div>
  </section>
</template>

<template id="content-editor">
  <section class="content-editor">
    <content-list :views="views" :remove="removeContentBlock" :update="updateContentBlock"></content-list>
    <button v-on:click="newContentBlock()">New Content</button>
  </section>
</template>

<template id="content-longtext">
  <div class="content-longtext">
    <textarea :value="inputData" v-on:input="updateContent"></textarea>
  </div>
</template>

<template id="content-image">
  <div class="content-image">
    <input type="file" />
  </div>
</template>

JavaScript

Vue.component('content-longtext', {
  template: '#content-longtext',
  props: {
    model: { type: String, required: true },
    update: { type: Function, required: true }
  },
  data() {
    return {
      inputData: this.model
    }
  },
  methods: {
    updateContent(event) {
      this.update(event.target.value)
    }
  },
})

Vue.component('content-image', {
  template: '#content-image',
})

Vue.component('content-list', {
  template: '#content-list-template',
  props: {
    remove: { type: Function, required: true },
    update: { type: Function, required: true },
    views: { type: Array, required: true }
  },
  methods: {
    removeContent(index) {
      this.remove(index)
    },
    updateContent(index) {
      return (content) => this.update(index, content)
    },
  },
})

Vue.component('content-editor', {
  template: '#content-editor',
  data() {
    return {
      views: [
        {type: 'content-longtext', model: 'test1'},
        {type: 'content-longtext', model: 'test2'},
        {type: 'content-longtext', model: 'test3'},
        {type: 'content-longtext', model: 'test4'},
        {type: 'content-longtext', model: 'test5'},
      ],
    }
  },
  methods: {
    newContentBlock(type) {
      this.views.push({type: 'content-longtext', model: ''})
    },
    updateContentBlock(index, model) {
      this.views[index].model = model
    },
    removeContentBlock(index) {
      this.views.splice(index, 1)
    },
  },
})

let app = new Vue({
  el: '#app'
})