Пример простой формы (state)

Пример кода для формы с собственным состоянием и внешней инициализацией

Код формы

<template>
  <form
    @submit.prevent="onSubmit"
    @reset.prevent="onReset"
  >
    <div>
      <input
        v-model.lazy="$v.name.$model"
        placeholder="Name"
      >

      <span v-if="$v.name.$error">
        {{ $v.name.$errors[0].messages }}
      </span>
    </div>

    <div>
      <input
        v-model.lazy="form.email"
        type="email"
        placeholder="Email"
      >

      <span v-if="$v.email.$error">
        {{ $v.email.$errors[0].messages }}
      </span>
    </div>

    <div>
      <button type="submit">
        Submit
      </button>

      <button type="reset">
        Reset
      </button>
    </div>
  </form>
</template>
import Vue, { PropType } from 'vue';
import { email, minLength, required } from '@vuelidate/validators';
import { ref, computed, watch, Ref } from '@vue/composition-api';

import { useForm } from '@/composition/form';

type Form = {
  name: string;
  email: string;
}

const defaultForm = () => ({
  name: '',
  email: '',
} as Form);

export default Vue.extend({
  props: {
    initForm: {
      type: Object as PropType<Form>,
      default: null,
    },
  },

  setup(props, context) {
    const form: Ref<Form> = props.initForm
      // Если форма имеет сложные сущности
      // то стоит изменить способ копирования
      ? ref({ ...props.initForm as Form })
      : ref(defaultForm());
    const reset = () => {
      form.value = defaultForm();
    };

    watch(() => props.initForm, (newVal) => {
      form.value = { ...newVal as Form };
    }, {
      // Стоит устанавливать, в зависимости от того,
      // как форма может обновляться из вне
      deep: false,
    });

    const rules = computed(() => ({
      name: {
        minLength: minLength(4),
        required,
      },

      email: {
        email,
        required,
      },
    }));

    const {
      v,
      onSubmit,
      onReset,
    } = useForm(context, { rules, form, reset });

    return {
      $v: v,
      onSubmit,
      onReset,
    };
  },
});

Код родителя

import Vue from 'vue';

const defaultForm = () => ({
  name: '',
  email: '',
});

export default Vue.extend({
  data: () => ({
    initForm: defaultForm(),
    pending: false,
  }),

  methods: {
    onSubmit(form) {
      // Стоит помнить, что возвращается буквально тот же обьект
      // формы, что и в компоненте формы, изменения здесь изменят и в компоненте
      console.log(form);
    },

    // Опционально, форма может сбрасываться как внутри
    // так и отсюда(если внутри формы отслеживается initForm)
    onReset() {
      this.initForm = defaultForm();
    },
  },
});