去年作的公司項目,最近再從作升級2.0版本。由於需求是用戶須要填寫五級地址,從省到你家的天然村。vue
以前一個項目作過,由於在整個項目中只用到了一次,也沒去封裝。git
如今用戶添加修改地址用得上,商家註冊,商家員工添加也要用上……那麼多場景我在不封裝要被打死……github
若是不想看文章的能夠直接去 gayhub 代碼就在這裏。ajax
咱們先分析一下需求。typescript
辣麼選擇地址的時候 有三種狀況設計模式
普通用戶: 5級地址選擇
商家員工: 3,4,5級地址選擇 (花q花q花q花q花q花q花q花q花q)
商家: 3級地址選擇
複製代碼
寫以前不妨先思考下咱們須要用到vue哪些東西?數組
組件註冊 註冊組件這個必然的。bash
prop 父組件給子組件傳遞數據 地址數據函數
$emit 調用父組件的方法 地址選擇完成後關閉彈窗。post
那麼開始寫代碼吧……
這裏呢咱們仍是使用vant……由於支持typescript啊……
新建項目
安裝依賴
啓動項目
複製代碼
具體的請看我上上篇文章……
這裏我已經把基礎的代碼寫好了,造了一些假的數據。假數據只是爲了方便編寫代碼。
想一想一件事情。普通用戶選擇地址的時候是5級,一股腦地選到底。商家呢則是3級,商家下面的員工則是3級4級5級均可以……
// AddressPicker.vue
private created() {
this.columns = this.province;
}
@Emit()
private close(data: any): any {
return data;
}
// 關閉操做
private onCancel() {
this.close(false);
}
// 肯定操做
private onConfirm(value: string) {
this.addressInfo.push(value);
if (this.selectLevel < this.level - 1) {
this.selectLevel++;
this.getAdddata(value);
} else {
this.close(this.addressInfo);
}
}
private getAdddata(addname: string) {
if (this.selectLevel === 1) {
this.columns = this.city;
} else if (this.selectLevel === 2) {
this.columns = this.county;
} else if (this.selectLevel === 3) {
this.columns = this.town;
} else if (this.selectLevel === 4) {
this.columns = this.village;
}
}
// Home.vue
<AddressPicker v-if="show" :level="level" @close="done"/>
private addressClass: number = 5;
private level = 5;
// 打開選擇框
private select(level: number) {
this.show = true;
this.level = level;
}
private done(data: any) {
if (data !== false) {
this.addressInfo = '';
data.map( (i: number) => {
this.addressInfo += i;
});
this.show = false;
} else {
this.show = false;
}
複製代碼
addname 呢是你選中以後的地址,根據你選中的地址發送請求到後臺獲取新的一輪地址。
我這裏只是爲了方便演示沒有作數據交互
那麼咱們ts+vue的組件就封裝好了。用了啥?prop 和 Emit,prop 傳遞數據這個不用說了,emit 實際上是爲了返回給父組件數據。
還有一個問題!!!!!
往後有需求變更,變成6級的只須要在getAdddata 裏再加一個if else。
那麼有沒有啥優化辦法呢?固然有了!這就要用到咱們的策略模式了!!!!
新建一個address.ts
// address.ts
export const getAaddress: any = {
1: (addname: string) => ['合肥', '蕪湖', '阜陽'], // 這裏對應的是一個ajax請求。
2: (addname: string) => ['潁上縣', '阜南縣', '臨泉縣', '太和縣'],
3: (addname: string) => ['鮦城鎮', '楊橋鎮', '韋寨鎮', '田橋鄉'],
4: (addname: string) => ['某某村', '羊村', '狼堡'],
};
// 在AddressPicker.vue 引入
import { getAaddress } from './address';
// 調用 並無if else !!!!!!
private getAdddata2(index: number, addname: string) {
this.columns = getAaddress[index](addname);
}
// 使用的時候也很方便
this.getAdddata2(this.selectLevel, value);
複製代碼
調用的時候傳一個key,和addname 參數,返回的時候是一條數組。
其實是調用的getAaddress對應得一個函數。
很是簡單的幾句話解決了if else 的問題。 後期拓展也很容易再加一句就完事了,下降了耦合度,各管各的。
this.getAdddata2 裏面沒有沒有直接獲取數據的操做,獲取數據的操做所有交給getAaddress 完成。這樣咱們能夠向又臭又長的if else 說拜拜了。
其實封裝組件不難,Prop,$emit 這些在 vue-property-decorator ,vue呢並無真正的支持typescript,只是一些語法糖讓開發人員對ts的一個慢慢過渡。
主要是我想引出策略模式消除if else。 下一篇文章想寫一下關於設計模式的代碼。
評論區一位老哥說的也是。再寫項目的時候儘可能少使用any,我這裏爲了省事,就沒有這麼去約束數據格式。
@Emit()
private close(data: any): any {
return data;
}
複製代碼
這裏的any呢由於點擊取消的時候咱們是關閉底部的選擇框,傳遞一個布爾值,選擇完地址呢則是返回一個對象數據。勤快點仍是寫倆個方法。偷懶一下嘛……
看到這裏了你還不點個贊評論一下嗎?