开发者问题收集

尝试创建通用输入组件

2016-11-24
2609

我正在开发一个 Web 应用程序,其中有很多表单需要创建,为此我使用了 Vue,因此我一直在尝试创建一个可以一直使用的通用输入组件。我使用的是 Bootstrap 网格,因此我的想法是,我应该能够向组件传递要占用的列数、标签、名称和用作 v-model 的属性。我想我已经差不多做到了,但我遇到了 props 变异的问题 - [Vue 警告]:避免直接变异 prop,因为每当父组件重新呈现时,该值都会被覆盖。相反,使用基于 prop 值的数据或计算属性。变异的 prop:“model” (在组件中找到)。 这是模板(简化形式):

 <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);
            }
        }

    }


});

这在另一个“edit-product”组件中使用,如下所示:

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

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

2个回答

实际上,我选择的解决方案比上面建议的更简单,实际上非常简单,取自 https://forum-archive.vuejs.org/topic/4468/trying-to-understand-v-model-on-custom-components/9

我不需要 'model' prop,我有一个 'value' prop,因此 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>

不同之处在于我实际上并没有尝试传递模型 prop,我只是传递一个值,并监听该值的变化。它似乎运行良好,并且足够干净和简单。我的下一个挑战是将一组任意属性传递给输入,但这是另一个问题的主题。

John Moore
2016-11-24

正如警告所建议的那样,您不应直接编辑要传递的值的 prop。

而是将其用作原始值,并在输入上设置一个单独的值 - 您可以将其传递给 v-model。如果您需要父级具有当前值,则还应传递一个 prop,以便您更新父级的参数,即

输入组件

# 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>
GuyC
2016-11-24