Vue.js:<input>的@input不适用于v-for

时间:2019-09-14 00:11:31

标签: vue.js html-input v-for

我正在创建自己的自定义<input> Vue组件。我正在做的是用户永远不会输入错误的输入类型。为此,我在每个输入处使用regex.test()

这是我的Vue组件的代码,用于获取整数元素或整数数组:

<template>
    <div>
        <label>{{ label }}
            <template v-if="isArray">
                <input 
                    v-model="arr[i - 1]" 
                    @input="filterInput" 
                    :disabled="disableWhen" 
                    v-for="i in arraySize" 
                    :key="i">
                </input>
            </template>
            <template v-else>
                <input 
                    v-model="num" 
                    @input="filterInput" 
                    :disabled="disableWhen">
                </input>
            </template>
        </label>
        <el-button 
            type="success" 
            icon="el-icon-check" 
            circle 
            @click="confirm" 
            :disabled="disableWhen">
        </el-button>
    </div>
</template>

<script>
    export default {
        props: {
            label: String,
            nonNegative: Boolean,
            disableWhen: Boolean,
            isArray: Boolean,
            arraySize: Number
        },
        data() {
            return {
                num: '',
                arr: []
            }
        },
        methods: {
            filterInput() {
                if (this.nonNegative) {
                    if (!/^[0-9]*$/.test(this.num)) {
                        this.num = '';
                    }
                } else if (!/^(-)?[0-9]*$/.test(this.num)) {
                    this.num = '';
                }
            },
            confirm() {
                if (this.isArray) {
                    let validArrayInput = true;
                    for (let i = 0; i < this.arraySize; i++) {
                        if (!this.validInput(this.arr[i])) {
                            validArrayInput = false;
                        }
                    }
                    if (validArrayInput) {
                        this.$emit('confirm', this.arr);
                    }
                } else if (this.validInput(this.num)) {
                    this.$emit('confirm', this.num);
                }
            },
            validInput(x) {
                return (x !== '' && x !== '-' && typeof x !== "undefined");
            }
        }
    }
</script>

isArray = false时,即对于整数元素,代码正常工作。但是在filterInput时永远不会调用方法isArray = true,并且对错误输入也没有任何限制。有什么问题吗?

1 个答案:

答案 0 :(得分:1)

filterInput对于这两种类型的输入都很好,但是它仅尝试操纵num,而不会更改arr

这是我要实现的尝试:

const MyInput = {
  template: `
    <div>
      <label>{{ label }}
        <template v-if="isArray">
          <input 
            v-for="i in arraySize" 
            v-model="arr[i - 1]" 
            :disabled="disableWhen" 
            :key="i"
            @input="filterInput" 
          >
        </template>
        <template v-else>
          <input 
            v-model="num" 
            :disabled="disableWhen"
            @input="filterInput"
          >
        </template>
      </label>
    </div>  
  `,

  props: {
    label: String,
    nonNegative: Boolean,
    disableWhen: Boolean,
    isArray: Boolean,
    arraySize: Number
  },
  
  data() {
    return {
      arr: []
    }
  },
  
  computed: {
    num: {
      get () {
        return this.arr[0]
      },
      
      set (num) {
        this.arr[0] = num
      }
    }
  },
  
  methods: {
    filterInput() {
      const arr = this.arr
      const re = this.nonNegative ? /^\d*$/ : /^-?\d*$/
      
      for (let index = 0; index < arr.length; ++index) {
        if (!re.test(arr[index])) {
          this.$set(arr, index, '')
        }
      }
    }
  }
}

new Vue({
  el: '#app',
  
  components: {
    MyInput
  }
})
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>

<div id="app">
  <my-input label="Single"></my-input>
  <br>
  <my-input label="Multiple" is-array :array-size="3"></my-input>
</div>

一些注意事项:

  1. 我将num更改为由arr[0]支持的计算属性。这简化了过滤逻辑,因为对于两种类型的输入都只需要考虑arr。它可以进一步简化,例如模板实际上不需要处理两种情况,它可以将单值与多值相同,但是array-size为1。只有发出的值(我的代码中未包含)才真正需要处理。对于单值案例有不同的行为。经过少许重构,num可能会被完全删除。
  2. 该实现是有状态的。如果您想从外部传递值,就会遇到困难。
  3. 我建议不要使用''除去不允许的字符,而不是将值设置为replace。我尚未在代码中进行此更改,我想保留原始示例中的行为。
  4. 关闭</input>标签无效,我已将其删除。
  5. 我尝试删除的filterInput方法中有很多重复项。现在,它将检查arr数组中的所有条目。似乎没有必要针对已更改的特定输入。
  6. this.$set用于按索引更新数组,否则反应系统(操纵数组的标准警告)将无法检测到它。