2017-06-07 47 views
2

我很難獲取父組件的屬性對象,並使用動態填充屬性使值在同一組件內可用。VueJs與父組件屬性對象的反應性

硬一點解釋,所以請看看下面的例子:

父組件

<script> 
    export default { 
     data() { 
      return { 
       fields: {}, 
      } 
     } 
    } 
</script> 

輔元件

<template> 
    <select 
     @change="update()" 
     v-model="field" 
    > 
     <option 
      v-for="option in options" 
      :value="option.value" 
     > 
      {{ option.name }} 
     </option> 
    </select> 
</template> 
<script> 
    export default { 
     props: { 
      initialOptions: { 
       type: Array, 
       required: true 
      } 
     }, 
     data() { 
      return { 
        field: '', 
       options: this.initialOptions 
      } 
     }, 
     mounted() { 
      if (
       (this.field === undefined || this.field === '') && 
       this.options.length > 0 
      ) { 
       this.field = this.options[0].value; 
      } 
      this.update(); 
     }, 
     methods: { 
      update() { 
       this.$emit('input', this.field); 
      } 
     } 
    } 
</script> 

DOM

<parent-component inline-template> 

    <div> 

     <child-component>   
      :initial-options="[{..}, {..}]" 
      v-model="fields.type_id" 
     ></child-component> 

    </div> 

    <div :class="{ dn : fields.type_id == 2 }"> 

     // ... 

    </div> 

</parent-component> 

使用Vue的控制檯,我可以看到fields對象獲取所有的子組件模型及其關聯的值,因爲它們發出input它們被安裝時,但是,對於一些奇怪的原因:class="{ dn : fields.type_id == 2 }"不追加類dn當選擇更改爲2。 Dom似乎並未反映父組件和子組件之間同步的更改。

有關如何使其工作的任何幫助?

+0

你如何添加屬性到父'fields'? – Bert

+0

在子組件上使用'v-model'指令,並在每個子組件的相關值上使用'mounted'發出'input'事件。 –

+0

你能證明嗎?我得到的是'fields'作爲一個空對象開始。如果您錯誤地添加屬性,Vue將無法檢測到更改。 – Bert

回答

2

以下是我正在評論的內容。 Vue cannot detect changes將動態添加到對象的屬性,除非使用$set添加它們。您的fields對象沒有type_id屬性,但因爲您使用的是v-model="fields.type_id"而被添加。因此,Vue不知道它何時發生變化。

在這裏,我已經添加了它,並且文字的顏色隨着您的預期而改變。

console.clear() 
 

 
Vue.component("child-component", { 
 
    template: ` 
 
    <select 
 
     @change="update()" 
 
     v-model="field" 
 
    > 
 
     <option 
 
      v-for="option in options" 
 
      :value="option.value" 
 
     > 
 
      {{ option.name }} 
 
     </option> 
 
    </select> 
 
    `, 
 
    props: { 
 
    initialOptions: { 
 
     type: Array, 
 
     required: true 
 
    } 
 
    }, 
 
    data() { 
 
    return { 
 
     field: '', 
 
     options: this.initialOptions 
 
    } 
 
    }, 
 
    mounted() { 
 
    if (
 
     (this.field === undefined || this.field === '') && 
 
     this.options.length > 0 
 
    ) { 
 
     this.field = this.options[0].value; 
 
    } 
 
    this.update(); 
 
    }, 
 
    methods: { 
 
    update() { 
 
     this.$emit('input', this.field); 
 
    } 
 
    } 
 
}) 
 

 
new Vue({ 
 
    el: "#app", 
 
    data: { 
 
    fields: { 
 
     type_id: null 
 
    } 
 
    } 
 
})
.dn { 
 
    color: red; 
 
}
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script> 
 
<div id="app"> 
 
    <div> 
 
    <child-component :initial-options="[{name: 'test', value: 1}, {name: 'test2', value: 2}]" v-model="fields.type_id"></child-component> 
 
    </div> 
 
    <div :class="{ dn : fields.type_id == 2 }"> 
 
    Stuff 
 
    </div> 
 
</div>

+0

這是一種恥辱,因爲這種方式我總是必須通過道具將它們傳遞給父控制器 - 所有這些都是絕對沒有理由的。 –

0

它看起來像你正試圖使一個可重複使用的組件。

我會問自己,當父組件必須處理一半以上的工作時,可重用組件的價值是什麼。該組件可以被更好地命名...

<DifficultToUseSelect/>. 

本質上講,你正在創建提供了一個組件,全部由自己,所有下面的HTML的...其他

<select></select> 

一切都是由管理父組件。

它可能會更有用做任何以下的...

  • 封裝在一個特定的選擇組件通常需要的選項,如

    StateAbbrevsSelect V型=「狀態」

  • 將數據模型的名稱傳遞給選定組件。然後該組件將通過該模型加載和管理自己的數據。

  • 將Web服務的URL傳遞給組件,然後調用它加載其選項。

同樣,我在這裏試圖傳達的主要觀點是製作一個可重用的組件,其中超過一半的工作量由父組件處理,實際上並不能很好地重用。