“透明”包装输入组件中的Vue双向绑定

问题描述 投票:1回答:2

我正在为<input>组件编写一个小包装器。我正在关注文档和这个tutorial

但是我遇到双向绑定问题。我希望我的组件能与v-model一起使用。绑定似乎适用于更新值,但是当我更改值本身时,组件不会更新。我也是read about transparent wrappers,这似乎是我的问题。

简单的例子:

<template id="numInput" :v-on="listeners">
  <div>
    <!-- note the div here, it works without, but that's not what I want -->
    <input ref:inp type="number" :value="num" @input="updateSelf($event.target.value)" @blur="reset" :class="{rc: isNegative}" />
  </div>
</template>

你可以找到整个代码示例here

绑定以一种方式工作(修改文本输入)。但是输入组件没有以其他方式更新(例如按钮klick)

欢迎任何帮助!

vue.js vuejs2 vue-component
2个回答
1
投票

自定义输入组件应该是无状态的(除非你有理由不这样做);这意味着组件的价值应该由道具而不是本地国家(数据)提供。你的<num-input>组件没有value支柱,这是v-model工作所需要的。

此外,您可能希望将inheritAttrs选项设置为false并手动绑定$attrs,因为您已将输入元素包装在div中。

以下是它应该如何的一个小例子:

Vue.component('num-input', {
  template: '#numInput',
  inheritAttrs: false,
  props: ['value'],
  computed: {
    isNegative() {
      return this.value < 0;
    },
  },
  methods: {
    onInput(e) {
      // You can conditionally do this after validation
      this.$emit('input', e.target.value);
    },
    onBlur() {
      if (this.isNegative) {
        this.$emit('input', 0);
      }
    },
  },
});

new Vue({
  el: '#app',
  data: {
    num: 0,
  },
});
.negative { color: red; }
<script src="https://rawgit.com/vuejs/vue/dev/dist/vue.js"></script>

<div id="app">
  <num-input v-model="num"></num-input>
  <button @click="num++">+1</button>
  <p>{{ num }}</p>
</div>

<template id="numInput">
  <div>
    <input type="number" :value="value" @input="onInput" @blur="onBlur" :class="{ negative: isNegative }" v-bind="$attrs">
  </div>
</template>

我没有强制input事件发出的值到一个数字(它是一个字符串),但我会把它留给你。


0
投票

这里有一些问题,但最根本的是你在代码中混合了nom和num。我稍微改造了你的组件并将你的num数据转换为属性,然后在你的主应用程序中绑定它。

这是你重写的代码......

Vue.config.devtools = true;

// global component registration
Vue.component('num-input', {
  template: '#numInput', 
  props: ['value'],
  computed: {
    isNegative: function() {
      console.log('num: ' + this.value)
      return this.value < 0;
    },
    listeners: function () {
      return this.$listeners;
    },
  },
  methods: {  
    reset () {
      if (this.isNegative) {
        this.$emit('input', 0)        
      }
    }
  },
});

 new Vue({
   el: '#container',
   data: {
     num: 0,
   },
   methods: {
     increaseBy1() {
       this.num++;
       console.log("increased by 1");
     },
   },
 });

为了查看代码和html绑定,我分叉了你的codepen,它可以在...找到

https://codepen.io/peterpde/pen/BOVQzg

© www.soinside.com 2019 - 2024. All rights reserved.