2017-09-23 63 views
0

我被困在我的孩子組件(自動完成)需要更新其父(曲線)的值的情況下,父母需要更新孩子或者當使用新的曲線組件時完全重新渲染)Vue2:警告:避免直接變異道具

在我的應用程序中,用戶可以在曲線組件列表中選擇曲線。我以前的代碼正常工作,除非組件自動完成未在列表中選擇另一個曲線時更新(組件未使用父項的值更新其值)。

這個問題已經得到解決,但我得到這樣的警告:

避免直接變異的一個道具,因爲該值將被覆蓋 每當父組件重新呈現。相反,使用基於prop值的數據或 計算屬性。支柱被突變: 「值」

此警告的說明正好解釋了我期望從我的組件中得到的行爲。儘管有這個警告,但這個代碼工作得很好!

下面是代碼(的部分內容已被刪除,以簡化)

// curve.vue 
<template> 
    <autocomplete v-model="curve.y"></autocomplete> 
</template> 


<script> 
    import Autocomplete from './autocomplete' 

    export default { 
    name: 'Curve', 
    props: { 
     value: Object 
    }, 
    computed: { 
     curve() { return this.value } 
    }, 
    components: { Autocomplete } 
    } 
</script> 


// autocomplete.vue 
<template> 
    <input type="text" v-model="content"/> 
</template> 

<script> 
    export default { 
    name: 'Autocomplete', 
    props: { 
     value: { 
     type: String, 
     required: true 
     } 
    }, 
    computed: { 
     content: { 
     get() { return this.value }, 
     set(newValue) { this.value = newValue } 
     } 
    } 
    } 
</script> 

很多人都得到同樣的警告,我嘗試了一些解決方案,我發現,但我不能讓他們的工作在我的情況下(使用事件,改變自動完成的道具的類型是一個對象,使用其他計算值,...)

有沒有簡單的解決方案來解決這個問題?我應該忽略這個警告嗎?

+0

:一個組件與V型工作您需要接受價值支持併發出輸入事件! –

回答

1

你可以忽略它,一切都會正常工作,但這是一個不好的做法,這就是vue告訴你的。當你不遵循單一責任原則時,調試代碼會更加困難。

Vue建議你,只有擁有數據的組件才能修改它。

不知道爲什麼事件解決方案($emit)在您的情況下不起作用,它會拋出錯誤或什麼?

要消除這個警告,你也可以使用.sync修改: https://vuejs.org/v2/guide/components.html#sync-Modifier

+0

使用'$ emit'和'$ on'並沒有引發任何錯誤,但是孩子沒有正確更新...... 但是用'v-on'替換'v-model',添加'.sync'和'$在計算值的setter中發射'工作! 非常感謝!我感覺有點愚蠢,我在文檔中花了很多時間而沒有看到'.sync' ... – Metikha

3

你可以嘗試是代碼,請按照prop - >local data - >$emit local data to prop中的每個組件和部件的包裝流程。

PS:$發射(「輸入」,...)是爲值更新(在道具)結合通過在doc V模型

// curve.vue 
<template> 
    <autocomplete v-model="curve.y"></autocomplete> 
</template> 


<script> 
    import Autocomplete from './autocomplete' 

    export default { 
    name: 'Curve', 
    props: { 
     value: Object 
    }, 
    data() { 
     return { currentValue: this.value } 
    } 
    computed: { 
     curve() { return this.currentValue } 
    }, 
    watch: { 
     'curve.y'(val) { 
     this.$emit('input', this.currentValue); 
     } 
    }, 
    components: { Autocomplete } 
    } 
</script> 


// autocomplete.vue 
<template> 
    <input type="text" v-model="content"/> 
</template> 

<script> 
    export default { 
    name: 'Autocomplete', 
    props: { 
     value: { 
     type: String, 
     required: true 
     } 
    }, 
    data() { 
     return { currentValue: this.value }; 
    }, 
    computed: { 
     content: { 
     get() { return this.value }, 
     set(newValue) { 
      this.currentValue = newValue; 
      this.$emit('input', this.currentValue); 
     } 
     } 
    } 
    } 
</script>