【问题标题】:Vue.js Input value gets deleted on first char onlyVue.js 输入值仅在第一个字符上被删除
【发布时间】:2017-11-20 13:18:38
【问题描述】:

基于官方示例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->Run 再次查看。

在第一个字符之后,一切都按预期工作。

如果我删除 v-bind:value="value" 或评论 \\this.hasValue = true 它会按预期工作。自定义 Input 组件推荐绑定 value 属性。

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

【问题讨论】:

    标签: vue.js vue-component


    【解决方案1】:

    这是预期的行为:

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

    那么如何解决这个问题?

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

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

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

    但是由于您使用了道具,并且我假设您想继续使用它,所以情况有点不同 - Vue 遵循“数据下降 - 事件上升”的模式。您不能从孩子内部更改道具,您必须告诉 父母 您想通过事件更改它。改变它的责任将是父母的。这是您具有正确父子关系的示例:

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

    【讨论】:

    • ... 导致组件重新渲染是我的关键。感谢您的深入解释。
    • 让组件重新渲染也是我的关键。如果它对任何人有帮助,我的想法是使用类似 ex: this.$el.querySelector('input').classList[hasValue]('has-value') where hasValue will be set before ex: const hasValue = Boolean (事件.目标.值)? 'add' : 'remove' 这将直接设置类并避免渲染
    【解决方案2】:

    您是否正在尝试实现这样的目标?

    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>

    【讨论】:

      【解决方案3】:

      我猜当您修改 hasValue 时,Vue 会重新渲染组件(将 has-value 类应用于 div),这会导致重新评估 v-bind:valuevalue 是一个未赋值且永远不会更改的道具,因此输入元素的值会被清除。

      您确实应该在输入元素上使用v-model,并根据模型中的value 控制has-value,而不是直接与DOM 交互。 (您将无法将v-modelvalue 一起使用,因为value 是一个道具,不能从组件内分配。)

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

      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: '',
        },
      });
      .my-input.has-value {
        background-color: yellow;
      }
      <script src="https://unpkg.com/vue@2.5.6/dist/vue.js"></script>
      
      <div id="app">
        <my-input v-model="value"></my-input>
      </div>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-10-23
        • 1970-01-01
        • 2020-09-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-20
        相关资源
        最近更新 更多