前言
去年做的公司项目,最近再从做升级2.0版本。因为需求是用户需要填写五级地址,从省到你家的自然村。
之前一个项目做过,因为在整个项目中只用到了一次,也没去封装。
现在用户添加修改地址用得上,商家注册,商家员工添加也要用上……那么多场景我在不封装要被打死……
如果不想看文章的可以直接去 gayhub 代码就在这里。
开始讲解
我们先分析一下需求。
- 用户填写地址的时候需要选到村
- 商家则是需要到县
- 商家员工呢可以选择到村,镇,县
辣么选择地址的时候 有三种情况
普通用户: 5级地址选择
商家员工: 3,4,5级地址选择 (花q花q花q花q花q花q花q花q花q)
商家: 3级地址选择
复制代码
编写代码
写之前不妨先思考下我们需要用到vue哪些东西?
-
组件注册 注册组件这个必然的。
-
prop 父组件给子组件传递数据 地址数据
-
$emit 调用父组件的方法 地址选择完成后关闭弹窗。
那么开始写代码吧……
这里呢我们还是使用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。 下一篇文章想写一下关于设计模式的代码。
看到这里了你还不点个赞评论一下吗?