一、報錯信息
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "isVisibleDialog"

二、概述
場景:點擊父組件的<顯示彈窗>按鈕顯示彈窗,
錯誤出現流程,點擊父組件<顯示彈窗>按鈕,彈窗顯示,點擊彈窗的取消按鈕,關閉彈窗的時候,就報錯啦
三、錯誤寫法
父組件
html
<dialog-f :is-visible-dialog="dialogData.isVisibleDialog" />
dialogData: { isVisibleDialog: false, }
methods
handleShowDialog(){ this.dialogData.isVisibleDialog = true; }
子組件
<el-dialog title="" :visible.sync="isVisibleDialog" :show-close="false" :close-on-click-modal="false" width="600px" custom-class="dialog-container" > <div slot="footer" class="mx-dialog-footer dis-flex flex-justify-end"> <div slot="footer" class="mx-dialog-footer dis-flex flex-justify-end"> <el-button class="dialog-footer-cancel" @click="isVisibleDialog=false">取消</el-button> <button class="dialog-footer-confirmed theme-bg-h-hover" type="primary" @click="sure" > 確定 </button> </div> </div> </el-dialog>
props
props: { isVisibleDialog: { type: Boolean, default() { return false; }, } }
錯誤原因
所有的 prop 都使得其父子 prop 之間形成了一個單向下行綁定:
父級 prop 的更新會向下流動到子組件中,但是反過來則不行。這樣會防止從子組件意外變更父級組件的狀態,從而導致你的應用的數據流向難以理解。
額外的,每次父級組件發生變更時,子組件中所有的 prop 都將會刷新為最新的值。這意味着你不應該在一個子組件內部改變 prop。如果你這樣做了,Vue 會在瀏覽器的控制台中發出警告。
官網提供了2種接近方案
這里有兩種常見的試圖變更一個 prop 的情形:
-
這個 prop 用來傳遞一個初始值;這個子組件接下來希望將其作為一個本地的 prop 數據來使用。在這種情況下,最好定義一個本地的 data property 並將這個 prop 用作其初始值:
props: ['initialCounter'], data: function () { return { counter: this.initialCounter } } -
這個 prop 以一種原始的值傳入且需要進行轉換。在這種情況下,最好使用這個 prop 的值來定義一個計算屬性:
props: ['size'], computed: { normalizedSize: function () { return this.size.trim().toLowerCase() } }
四、正確寫法
父組件
html
<dialog-f
:is-visible-dialog="dialogData.isVisibleDialog"
/>
dialogData: {
isVisibleDialog: 0, }
methods
handleShowDialog(){
this.dialogData.isVisibleDialog = Math.random()*10 + 1; }
子組件
<el-dialog
title=""
:visible.sync="isShowDialog"
:show-close="false"
:close-on-click-modal="false"
width="600px"
custom-class="dialog-container" >
<div slot="footer" class="mx-dialog-footer dis-flex flex-justify-end">
<div slot="footer" class="mx-dialog-footer dis-flex flex-justify-end">
<el-button class="dialog-footer-cancel" @click="isVisibleDialog=false">取消</el-button>
<button
class="dialog-footer-confirmed theme-bg-h-hover"
type="primary"
@click="sure"
>
確定
</button>
</div>
</div>
</el-dialog>
props:
props: {
isVisibleDialog: {
type: Number,
default() { return 0; }, } }
data() { return { isShowDialog: false } }
watch: { isVisibleDialog(val) { this.isShowDialog = val ? true : false } }
