Вопрос: Нормально ли использование VUE JS только для работы с формами, придания реактивности и тд?

Лучший ответ: Можно и нужно. Это один из плюсов этого фреймворка.

Худший ответ: Vue примечателен хотя бы тем, с какой легкостью он интегрируется в уже существующие проекты. Набор возможностей этой библиотеки, на мой взгляд лучшая реализация MVVM. Допустим на вашем сайте есть jQuery слайдер–калькулятор, вы добавили плагин для чата с онлайн–консультантом и вам нужно передавать данные в чат. Добавив модель представления, в виде Vue приложения, вы можете легко управлять данными и моделью представления:<body>
  <div id="app">
    <p> {{ calculationResult | rub }}</p>
    <!-- Плагин range slider инициализируется через директиву
           В кавычка объект из binding.value из сигнатуры хука -->
    <div v-range-slider="{ min: 0, max: 10 }"></div>
    <!-- Подписка на события осуществляется прямо в html -->
    <button @click="sendToChat">Отправить в чат</button>
    <button @click="toggleChat">Открыть чат</button>
    <button @click="toggleChat">Закрыть чат</button>
    <!-- Чат изолирован от остальной разметки в отдельный компонент -->
    <chat-app v-show="isChatOpen" :result="calculationResult" />
  </div>
</body>Vue.component('chat-app', {
  // Шаблон это HTML + суперспособности vue, например ref
  template: '<div ref="chat"></div>',
  // Аргумненты компонента, позволяет делать
  // - аннотации типов
  // - валидация
  // - дефолтные значения
  props: {
    result: { type: Number }
  },
  mounted() {
    // Здесь нет смысла использовать директиву, инициализируем чат когда компонент окажется в ДОМе
    // Вместо селекта элемента по например id, мы напрямую получаем из ранее созданной рефки
    this.chatInstance = new SomeChatPlugin(this.$refs.chat)
  },
  watch: {
    // При изменении пропа result, в текстовое поле чата будет добавлен текст
    result(newValue) {
      this.chatInstance.fillText(newValue)
    }
  }
})

new Vue({
  el: '#app',
  filters: {
    // Фильтры это особый способ вызова функции
    // rub(value) === value | rub
    rub(v) {
      const value = Math.round(v)
      switch(value) {
        case 1: return `${value} рубль`
        case 2:
        case 3:
        case 4: return `${value} рубля`
        default: return `${value} рублей`
      }
    }
  },
  directives: {
    rangeSlider: {
      // Директивы имеют свой жизненный цикл
      // Хук inserted это ближайшее к $(document).ready() событие
      /**
        * @param {HTMLElement} el
        * @param {Object} binding https://ru.vuejs.org/v2/guide/custom-directive.html#Аргументы-хуков
        * @param {Vue} context vue instance
        */
      inserted(el, binding, context) {
        $(el).someFancyRangeSlide(binding.value)
          .on('move', newValue => context.updateValue(newValue))
          // События выпускаемые jquery будут обработаны vue
      }
    }
  },
  data() {
    return {
      value: 0,
      calculationResult: 0,
      isChatOpen: false,
    }
  },
  methods: {
    updateValue(newValue) {
      this.value = newValue
    },
    thoggleChat() {
      this.isChatOpen = !this.isChatOpen
    },
    sendToChat() {
      this.calculationResult = this.value
    }
  }
})
Пример синтетический и упрощённый. Однако, ярко иллюстрирует как и зачем интегрировать Vue в любое MVC приложение, или даже в статический сайт. В прочем всё это не плохо покрывается jQuery, однако решать вам.