Vue2.0 之props是資料綁定出錯
背景
在使用Vue進行元件開發時,對於父元件傳遞過來的props屬性,在子元件內部對這個值進行了更改,就會出現如下的錯誤資訊:
[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: "xxx"
錯誤原因
在Vue2.X中,傳入的props屬性是不允許改變的,因為在新的渲染機制中,每當父元件重新渲染時,子元件都會被重新覆蓋,所以props屬性,在子元件內部應該被看做是不可變物件。所以我們必須藉助中間變數來做緩衝,通過中間變數的改變傳送事件給父元件,父元件接收到後,再對props進行更改。
案例
在實現公司內部元件時,我引用了element-ui的Dialog元件,為了方便元件的複用,我將一些基礎屬性封裝在了一個自定義元件中,大致的結構如下:
- 外部Index是用於組裝自定義的元件
- 自定義元件是一些可以複用的基本功能元件
- 最裡面的是引用的elementUI
為了控制彈出框的顯示情況,所以我定義了一個Visible
屬性,
Visible
的流向是:
在element-ui元件中 ,控制顯示的一般會加上這個屬性:visible.sync="visible"
這個意思是說elementui元件在內部改變visible
之後會通知父元件visible
屬性更新了。它的變化會回傳給父元件,所以當時在自定義元件中拿到這個值就對其進行操作,發現報錯了。此時的資料流向如下:
但是由於elementUI直接就將變化給回傳了,所以我們不能直接傳給Index元件,需要藉助一箇中間變數來接受這個值,然後把這個變化回傳給Index元件,告訴Index自定義元件需要更新。
解決方式
首先我們頂一下Index元件需要傳的值:
<user-dialog :showDialog.sync="dialogTableVisible" :ruleForm="ruleForm" v-if="dialogTableVisible"
@closeDialog="closeUserDialog"></user-dialog>
dialogTableVisible
屬性傳入到user-dialog
自定義的元件中
自定義的元件
props: {
showDialog: {
type: Boolean,
default: false
}
},
data(){
return {
//show控制elementui的變化
show: false,
}
}
//建立時,賦值
created() {
this.show = this.showDialog;
},
我們藉助show
作為中轉變數,當show發生變化時,我們傳送事件給Index元件
所以,在關閉elementui時,觸發一個回撥函式:
closeDialog() {
this.show = false;
this.$emit('closeDialog');
},
父元件可以通過監聽這個事件來關閉自定義元件:
<user-dialog :showDialog.sync="dialogTableVisible" :ruleForm="ruleForm" v-if="dialogTableVisible"
@closeDialog="closeUserDialog"></user-dialog>
事件方法:
closeUserDialog() {
this.dialogTableVisible = false;
},
解決方式二
通過事件Bus來傳遞事件
import Vue from 'vue'
const Bus = new Vue()
var app= new Vue({
el:'#app',
data:{
Bus
}
})
直接建立一個空Vue例項,作為訊息匯流排承載體,然後在子元件中通過
this.$root.Bus.$on()
,this.$root.Bus.$emit()
來呼叫.
不需要走props,子元件改變就呼叫$emit('xxx')
傳送事件
父元件只需要監聽$on('xxx')
然後操作傳入的屬性值即可。