试图创建通用输入组件

时间:2016-11-24 15:42:11

标签: vue.js

我在我正在使用的网络应用中创建了很多表单,我正在使用Vue,所以我一直在尝试创建一个我可以使用的通用输入组件始终。我使用的是Bootstrap网格,因此我的想法是我应该能够传递组件的多个列,标签,名称和属性以用作v模型。我想,我有点到达那里,但我遇到了变异道具的问题 - [Vue警告]:避免直接改变道具,因为只要父组件重新渲染,该值就会被覆盖。而是根据prop的值使用数据或计算属性。支持变异:"模型" (在组件中找到)。 这是模板(简化形式):

 <template id="field">
<div v-bind:class="colsClass">

    <div class='form-group form-group-sm'>
        <label v-bind:for="name">{{labelText}}</label>

        <input v-bind:id='name' ref="input" class='form-control' v-bind:name='name' v-model='model'/>

    </div>
</div>

这是(再次简化)JS:

Vue.component('field', {

    template: '#field',

    props: ['cols','label','group','name','model'],


    computed:{
        colsClass:function(){
            return "col-xs-"+this.cols
        }
        ,
        labelText:function(){
            if(this.label) {
                return this.label
            } else {
                return _.startCase(this.name);
            }
        }

    }


});

这是在另一个&#39;编辑产品中使用的。组件,像这样:

<field :cols="8" name="name" :model="product.name"></field>

这会显示OK,但是当我编辑字段的值时会抛出错误(或更准确地说,警告)。那么我做错了什么?

2 个答案:

答案 0 :(得分:1)

正如警告所示,你不应该直接编辑你传递的道具。

而是将其用作原始值并在其输入上设置单独的值 - 您可以将其传递给v模型。如果您需要父项具有当前值,那么还要传递一个支柱,允许您更新父项的参数,即

输入组件

# script
props: [
  'origValue',
  'valueChange',
],
data: {
  inputValue: '',
  ...
},
mounted () {
  this.inputValue = this.origValue
},
watch: {
  inputValue () {
    this.valueChange(this.inputValue)
  },
  ...
},
...

# template
<input type="text" v-model="inputValue">

<强>父

# script
data () {
  return {
    fieldValue: 'foo',
    ...
  },
},
methods: {
  updateField (value) {
    this.fieldValue = value
  },
  ...
},
... 

# template
<field :value-change="updateField" :orig-value="fieldValue"></field>

答案 1 :(得分:1)

实际上,我所采用的解决方案比上面提到的解决方案简单得多,实际上非常简单,取自https://forum-archive.vuejs.org/topic/4468/trying-to-understand-v-model-on-custom-components/9

我不想要'模型'道具,我有一个“值”,所以JS改为:

Vue.component('field', {

template: '#field',

props: ['cols','label','group','name','value'],


computed:{
    colsClass:function(){
        return "col-xs-"+this.cols
    }
    ,
    labelText:function(){
        if(this.label) {
            return this.label
        } else {
            return _.startCase(this.name);
        }
    }

}
});

模板变为:

    

    <div class='form-group form-group-sm'>
        <label :for="name">{{labelText}}</label>

        <input :id='name' :name='name' class='form-control' :value="value" @input="$emit('input', $event.target.value)"/>

    </div>
</div>

我这样使用它:

<field :cols="8" name="name" v-model="product.name"></field>

不同之处在于我实际上并没有尝试传递模型支撑,我只是传递一个值,并且正在侦听对该值的更改。它似乎工作得很好,干净,简单。我的下一个挑战是将一组任意属性传递给输入,但这是另一个问题的主题。