Custom Vue Material md-Input 如何获取 isDirty 或 isTouched

Custom Vue Material md-Input how to get isDirty or isTouched

我想创建自己的 CustomMdInput,并进行基本验证。我想实现这样的输入:

我使用 <fp-input v-model="test"></fp-input>,重要的是,当需要此输入时,当有人点击它或输入内容时(变成 'touched' 或 'dirty' 属性), 接下来散焦这个输入并转到另一个输入,前一个输入在所有验证中保持无效,所以我有这样的东西:

<template>
  <div class="md-layout-item">
    <md-field>
      <label :for="id">Imię</label>
      <md-input :name="id" :id="id" :required="required" v-model="value" :ref="id" @input="emitValue()"></md-input>
      <span class="md-error">Imię jest obowiązkowe</span>
    </md-field>
  </div>
</template>

<script>
export default {
  name: 'FpInput',
  props: {
    value: {
      required: true
    },
    id: {
      required: true,
      type: String
    },
    required: {
      default: false,
      type: Boolean
    }
  },
  methods: {
    emitValue () {
      this.$emit('input', this.$refs[this.id].value)
    }
  }
}
</script>

<style scoped>

</style>

但是我不知道如何检查这个输入是脏的还是被触摸的,以及我如何设置这个输入的有效性以在提交后检查 isFormValid

举个例子

const MyInput = {
   template: '#myInput',
   props: ['value'],
   data () {
    return {
     inputValue: this.value,
     dirty: false,
     touched: false,
     inValid: false
    }
   },
   methods: {
    validate () {
     if(this.inputValue.length<5){
      this.inValid = true
      this.dirty = true
     }else{
      this.inValid = false
      this.dirty = false
      this.touched = false
     }
    },
    emitValue() {
     this.validate()
     this.$emit('input', this.inputValue);
    }
   }
  }

  var app = new Vue({
    el: '#app',
    components: {MyInput},
    data () {
      return {
      }
    }
  })
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
 <div id="app">
   <my-input value="5"></my-input>
 </div>

 <script type="text/x-template" id="myInput">
  <div>
        <input v-model="inputValue" @input="emitValue()" @touchstart="touched = true" @mousedown="touched = true"/>
   <span v-show="(dirty || touched) && inValid">must be at least 5 letters</span>
   <div>dirty:{{dirty}}</div>
   <div>touched:{{touched}}</div>
   <div>inValid:{{inValid}}</div>
  </div>
 </script>

给你一个完整的例子

const MyInput = {
  template: '#myInput',
  props: ['value'],
  data () {
    return {
      inputValue: this.value,
      dirty: false,
      touched: false,
      inValid: false
    }
  },
  methods: {
    validate () {
      if(('' + this.inputValue).length<5){
        this.inValid = true
        this.dirty = true
      }else{
        this.inValid = false
        this.dirty = false
        this.touched = false
      }
    },
    emitValue(e) {
      this.validate()
      this.$emit('input', this.inputValue);
    }
  },
  created () {
    this.inputValue = this.value;
    this.validate();
    this.dirty = false;
  }
}

var app = new Vue({
  el: '#app',
  components: {MyInput},
  data () {
    return {
      inputList: new Array(4).fill('').map(o=>({val:5}))
    }
  },
  methods: {
    submit () {
      if(this.$refs.inputs.some(o=>o.inValid)){
        alert('you have some input invalid')
      }else{
        alert('submit data...')
      }
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
 <div id="app">
  <form @submit.prevent="submit">
      <my-input ref="inputs" v-for="item in inputList" v-model="item.val"></my-input>
    <button type="submit">submit</button>
  </form>
</div>

<script type="text/x-template" id="myInput">
  <div>
        <input v-model="inputValue" @input="emitValue()" @touchstart="touched = true"/>
    <span v-show="(dirty || touched) && inValid">must be at least 5 letters</span>
  </div>
</script>