2016-11-24 44 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> 

不同的是,我沒有真正試圖通過一種模式支撐下,我只是路過的值,並監聽更改該值。它似乎工作得很好,很乾淨,很簡單。我的下一個挑戰是將任意一組屬性傳遞給輸入,但這是另一個問題的主題。