2016-11-24 71 views
1

我有很多窗体可以在我正在使用的Web应用程序中创建,为此我使用Vue,所以我一直试图创建一个可以使用的通用输入组件始终。我使用的是Bootstrap网格,所以我的想法是,我应该能够传递组件的许多列来占用,标签,名称和属性用作v模型。我觉得,我有点不习惯,但是我遇到了一个突变道具的问题 - [Vue warn]:避免直接改变道具,因为只要父组件重新渲染,值就会被覆盖。相反,使用基于道具值的数据或计算属性。支柱正在发生变异:“型号” (在组件中找到)。 这里是模板(以简化形式):试图创建通用输入组件

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

    } 


}); 

这从另一个 '编辑产品' 组件中使用,像这样:

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

这显示确定,但抛出错误(或更多精确度伊利,警告),当我编辑字段的值。那么我做错了什么?

回答

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

其实,我已经走了该解决方案是一个比上述建议相当简单,其实很简单,从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> 

不同的是,我没有真正试图通过一种模式支撑下,我只是路过的值,并监听更改该值。它似乎工作得很好,很干净,很简单。我的下一个挑战是将任意一组属性传递给输入,但这是另一个问题的主题。