前言:使用Vue進行項目開發的時候,通常會用到Vue提供的組件化機制封裝開發所需要的組件以達到開發項目的需求,大到項目中的一快篩選模塊、數據表格,小到分頁面板、級聯面板、乃至一個小小的button按鈕,之所以組件化也是爲提高我們實際的開發效率,那到底什麼是組件化呢?參考一張尤玉溪大大的圖就會很快明白;
簡單來講一個完整項目會分爲很多部分,每個部分都會有各自獨立的功能,每個獨立的功能組件又是由很多小的組件構成,瞭解了什麼是組件之後,就必須要明白組件之間的通訊方式。Vue官方爲我們提供了子傳父、父傳子的方法以及屬性,但是單純使用這些是遠遠不能夠滿足我們的實際開發需求,因爲很多時候我們需要父組件與子組件直接雙向綁定數據,但是Vue中父子組件通信,都是單項的數據流,具體如下:
父組件:
<!-- 父組件 -->
<template>
<div class="Parent">
<el-col :span="12">
<el-card class="box-card">
<div slot="header" class="clearfix">
<h2>Parent(父組件)</h2>
<el-button style="float: right; padding: 3px 0" type="text">查看詳情</el-button>
</div>
<el-button type="primary" icon="el-icon-plus" circle @click.native="Add(off)"></el-button>
<Children :Data="off"></Children>
<el-col :span="12">
<span>來自子組件的數據:</span>
{{msg}}
</el-col>
</el-card>
</el-col>
</div>
</template>
子組件:
<!-- 子組件 -->
<template>
<div class="Children">
<el-dialog
width="30%"
top="15%"
title="Children(子組件)"
:visible.sync="off"
:before-close="handleClose"
modal-append-to-body="false"
append-to-body="false"
>
<el-input v-model="input" placeholder="請輸入內容"></el-input>
<span slot="footer" class="dialog-footer">
<el-button @click="off = false">取 消</el-button>
<el-button type="primary" @click="off = false">提 交</el-button>
</span>
</el-dialog>
</div>
</template>
預覽:
功能:父組件點擊“+”按鈕之後調用子組件,子組件提交數據、父組件藍色部分顯示子組件提交的數據;
思路:首先得明白子組件顯示與否依賴於off,也就是點擊"+"號之後,父組件必須改變子組件的off值(子組件數據),父組件data裏必須也有個off值用於傳遞數據(父組件數據),從而達到父子組件數據雙向綁定的需求;
接下來改造代碼:
<!-- 父組件 -->
<template>
<div class="Parent">
<el-col :span="12">
<el-card class="box-card">
<div slot="header" class="clearfix">
<h2>Parent(父組件)</h2>
<el-button style="float: right; padding: 3px 0" type="text">查看詳情</el-button>
</div>
<el-button type="primary" icon="el-icon-plus" circle @click.native="Add()"></el-button>
<Children :Data="off" @GetData="GetData"></Children>
<el-col :span="12">
<span>來自子組件的數據:</span>
{{msg}}
</el-col>
</el-card>
</el-col>
</div>
</template>
<script>
import Children from "./Children"; //引入Children
export default {
components: {
Children
},
data() {
return {
msg: "暫無", //穿傳遞初始數據
off: false
};
},
methods: {
Add() {
this.off = true; //修改off 打開子組件
},
GetData(off,input) { //這裏的off是接收子組件傳遞過來的值
this.off = off; //把子組件的數據同步到父組件中
this.msg = input; //同上
}
}
};
Parent解釋:在父組件中引入子組件Children,使用v-bind綁定父組件的off傳遞給子組件,當點擊“+”號之後執行Add方法改變off爲true,使用自定義事件監聽子組件事件是否觸發,觸發之後接收到來自子組件的數據並同步更新到父組件對應的狀態;
<!-- 組件說明 -->
<template>
<div class="Children">
<el-dialog
width="30%"
top="15%"
title="Children(子組件)"
:visible.sync="off"
:modal-append-to-body="false"
:append-to-body="false"
>
<el-input v-model="input" placeholder="請輸入內容"></el-input>
<span slot="footer" class="dialog-footer">
<el-button @click="Submit(0)">取 消</el-button>
<el-button type="primary" @click="Submit(1)">提 交</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
components: {},
data() {
return {
input: "",
off: this.Data //賦初始值 等價於off:false
};
},
props: ["Data"], //接收來自父組件的數據
watch: {
Data(N, O) {
this.off = N; //每次Props數據改變的時候同步更新到off
}
},
methods: {
Submit(key){
if(key){ //點擊提交按鈕
alert("提交!")
// if(....) //此處編寫表單效驗通過後的業務邏輯
this.off = false
}else if(!key){
alert("取消!") //點擊取消按鈕
this.off = false
}
this.$emit('GetData',this.off,this.input)
}
}
};
</script>
Children解釋:props對象接收父組件數據,組件創建完畢之後第27行初始化來自父組件的數據(此處由於父組件中off值爲false,所以第一次賦值也是false,注意這裏只能賦初始值 後面的父組件傳遞的數據將不會改動,必須由watch監聽變化再更新到data > off),取消/提交調用Submit方法,(38行kye==1 1隱式轉換之後爲true所以不用麻煩寫if(key==1),42行同理),執行Submit之後改變off的值爲false即關閉子組件,並且使用$emit創建自定義事件GetData (此處GetData必須與父組件中第11行綁定的方法一致纔可以觸發自定義事件),觸發子組件的GetData事件並且同步更新到父組件中;
至此 結束,看一下效果!