Typescript版本VUE+组件封装+最简单的策略模式,地址选择

前言

去年做的公司项目,最近再从做升级2.0版本。因为需求是用户需要填写五级地址,从省到你家的自然村。

之前一个项目做过,因为在整个项目中只用到了一次,也没去封装。

现在用户添加修改地址用得上,商家注册,商家员工添加也要用上……那么多场景我在不封装要被打死……

如果不想看文章的可以直接去 gayhub 代码就在这里。

开始讲解

我们先分析一下需求。

  • 用户填写地址的时候需要选到村
  • 商家则是需要到县
  • 商家员工呢可以选择到村,镇,县

辣么选择地址的时候 有三种情况

 普通用户: 5级地址选择 

 商家员工: 3,4,5级地址选择 (花q花q花q花q花q花q花q花q花q)

 商家: 3级地址选择 
复制代码

编写代码

写之前不妨先思考下我们需要用到vue哪些东西?

  • 组件注册 注册组件这个必然的。

  • prop 父组件给子组件传递数据 地址数据

  • $emit 调用父组件的方法 地址选择完成后关闭弹窗。

那么开始写代码吧……

这里呢我们还是使用vant……因为支持typescript啊……

新建项目
安装依赖
启动项目
复制代码

使用typescript+vue 编写电影信息小项目!

具体的请看我上上篇文章……

这里我已经把基础的代码写好了,造了一些假的数据。假数据只是为了方便编写代码。

想想一件事情。普通用户选择地址的时候是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。 下一篇文章想写一下关于设计模式的代码。

看到这里了你还不点个赞评论一下吗?

猜你喜欢

转载自juejin.im/post/5bf8099e6fb9a049ec6ab8e3