Vue.js输入值仅在第一个char上被删除

时间:2017-11-20 13:18:38

标签: vue.js vue-component

基于官方示例Custom Input Component example:

HTML:     

<div id="app" >
  <div :class="{'has-value' : hasValue}">
    <input type="text"
      ref="input"
      v-bind:value="value"
      @input="onInput" >
  </div>
</div>

JS:

new Vue({
  el: '#app',
  data: function() {
    return {
      hasValue: false
      }
  },
  props: ['value'],
  methods:{
  onInput: function(){
    val= this.$refs.input.value
      if(val && val.length > 0){
        this.hasValue = true
      } else {
        this.hasValue = false
      }
    }
  }
})

JS Fiddle

预期: 动态设置hasValue数据以进行输入,并将Css类绑定到此数据

意外的: 只有在初始化并键入第一个字符后,才会从输入中删除键入的字符。按JS-Fiddle-&gt;运行再次查看。

在第一个角色之后,一切都按预期工作。

如果我删除v-bind:value="value"或评论\\this.hasValue = true,则按预期方式工作。对于自定义输入组件,建议使用绑定值prop。

这是为了什么?为什么?或者这是我应该报告的错误?

3 个答案:

答案 0 :(得分:6)

这是预期的行为:

  • 插入第一个字符后,hasValuefalse更改为true,导致组件重新呈现
  • 在重新渲染期间,Vue会看到输入有一个值(您刚输入的字符),但您绑定到它的属性(value道具)是空的。
  • 因此,Vue更新输入以匹配绑定的prop - 因此,它会清空输入。
  • 之后,hasValue不再发生变化,因此无法重新渲染,因此,Vue不再重置输入字段的值。

那么如何解决这个问题?

首先,您必须了解Vue是数据驱动的 - 数据决定HTML,而不是相反。因此,如果您希望输入具有值,则必须在绑定到它的属性中反映该值。

如果使用本地数据属性,这将是微不足道的:

https://jsfiddle.net/Linusborg/jwok2jsx/2/

但是既然你使用了道具,并且我假设你想继续使用道具,那么这种情况就会有所不同 - Vue遵循“数据向下 - 事件向上”的模式。你不能在孩子内部改变道具,你必须告诉你从中得到它的,你想用事件来改变它。改变它的责任将是父母的责任。以下是具有正确父子关系的示例:

https://jsfiddle.net/Linusborg/jwok2jsx/4/

答案 1 :(得分:0)

我猜测当你修改hasValue时,Vue会重新渲染组件(将has-value类应用于div),这会导致v-bind:value被重新设置-evaluated。 value是一个未分配且永不改变的prop,因此输入元素的值被清除。

您确实应该在输入元素上使用v-model并根据模型中的has-value控制value,而不是直接与DOM进行交互。 (虽然v-model是道具并且无法从组件中分配,但您仍然无法将valuevalue一起使用。)

我还猜测你想制作一个自定义输入组件,当它有一个值时应用某种风格。试试这个:

&#13;
&#13;
Vue.component('my-input', {
  props: ['value'],
  template: `<input class="my-input" :class="{ 'has-value': value }" type="text" :value="value" @input="$emit('input', $event.target.value)">`,
});

new Vue({
  el: '#app',
  data: {
    value: '',
  },
});
&#13;
.my-input.has-value {
  background-color: yellow;
}
&#13;
<script src="https://unpkg.com/vue@2.5.6/dist/vue.js"></script>

<div id="app">
  <my-input v-model="value"></my-input>
</div>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

你想要达到这样的目标吗?

new Vue({
  el: '#app',
  data: {
    input: ''
  },
  computed: {
    hasValue () {
      return this.input.length ? true : false
    }
  }
})
.has-value {
  background-color: red;
}
<div id="app">
  <div :class="{'has-value' : hasValue}">
    <input type="text" v-model="input">
  </div>
</div>

<script src="https://unpkg.com/vue"></script>