Vue3.2: 仿飞书App选址组件封装(TDesign)

简介: 有一件事不得不承认,飞书在应用桌面端组件开发方面,还是做得比较优秀的,特别是在用户体验方面适用不同人群。如果做得很一般,那么也就不会有这么多产品设计者,争先相仿飞书的产品了,哈哈哈😄,其中也包括我身边的产品同事。既然说到这了,那么咋们先看下模仿的效果图吧,观摩一二

一、简介

有一件事不得不承认,飞书在应用桌面端组件开发方面,还是做得比较优秀的,特别是在用户体验方面适用不同人群。如果做得很一般,那么也就不会有这么多产品设计者,争先相仿飞书的产品了,哈哈哈😄,其中也包括我身边的产品同事。既然说到这了,那么咋们先看下模仿的效果图吧,观摩一二,如下:

image.png

那么有JYM好奇,会问,飞书的地址选择器又是咋样的呢?继续往下看:

二、飞书APP地址选址组件

image.png

从图片中可以看出,飞书的地址选择组件,包括了三部分:(国家、省市区、详细地址)
而我们产品的设计,则是将国家省市区嵌套在一起,进行组件联动,这个待会后面再说。

我们先继续看飞书APP,

国家的弹层选择是怎样子的:

image.png

其中,分为推荐(即热门)字母分类搜索 两大部分,对全球国家进行分组和定位。当选择国家后,则会依据选择的国家重新请求省市区中的数据。大致就这么一个逻辑

省市区的弹层是怎样子的

image.png

先选省份,然后拉城市的数据,选完城市,再拉区县的数据,如果所得到的下级数据数组为空则不展示该分层及后面的后面的分层。当然,这里还提供了暂不选择的方式,就是不一定需要选择到最后一层才能结束地址选择并关闭弹层。也可以直接点击 暂不选择按钮 关闭弹层,并以上一层的选择目标为结果集,回显到输入框中。

在这里,之所以先通过体验飞书选址组件的,也是为了后面的逻辑分析和模仿。

三、仿飞书选址组件

设计思路

  1. “热门”里面的数据为系统可配默认值为:中国、中国澳门、中国香港、中国台湾、越南、新加坡、美国
  2. 初始值根据用户网络环境自动定位,定位失败则默认空
  3. 下拉框带有搜索功能,可搜索国家/地区名称,模糊实时搜索
  4. 交互:
    • (1)选择了上一层,才出现下一层的tab,直到最后一层选中后关闭下拉框
    • (2)“暂不选择”则关闭下拉框,只填入这层之前选择的值,此按钮需要根据场景需求来,可隐藏掉

注意:当前页面上“组织地址”下拉中隐藏掉“暂不选择”按钮,需要用户选到最后一个层级的值

接口定义

从设计图中的信息,我们无法需要这些信息:字段名称、唯一值代号、以及所依附的父级代号,形成一个完整的国家省市区的关系链树状结构。但是,因考虑到性能的问题,我们不可能要求后端接口一次性返回所有国家省市区所组合而成的的庞大数状结构数据,那么我们或许可以将其拆分成一个单元结构即树叶,再通过按需,将整个单元结构串联起来形成躯干。

如此做法,一来可以按照用户所需加载数据,二来提高性能和响应速度。也方便后续地址数据的维护。

所以定义了如下单元结构:

export interface Region {
   
   
    /**
     * 区域简称
     */
    area?: string;
    /**
     * 区域代码,身份证头两位
     */
    code?: string;
    /**
     * 导入时间
     */
    create_at?: number;
    /**
     * 名称
     */
    name?: string;
    /**
     * 所属区域代码
     */
    parent: string;
}

然后通过行政区域代号去请求,得到区域列表

请求参数:body

export interface Request {
   
   
    /**
     * 所属区域代码,不知道就传空
     */
    code: string;
}

请求结果:response

export interface Response {
    /**
     * 行政区域列表
     */
    regions: Region[];
}

示例结果:

image.png

开发组件(基于TDesign框架)

我们先对需求进行分析,理清开发思路即可

1.设置四个分类常量

const topBar: Array<TabItem> = [
  {
    value: "country",
    label: "国家",
  },
  {
    value: "province",
    label: "省份/地区",
  },
  {
    value: "city",
    label: "城市",
  },
  {
    value: "area",
    label: "区/县",
  },
];

2.入参定义

const props = defineProps({
  // data: {
  //     type: Object,
  //     default: () => {},
  // },
  value: {
    type: Object,
    default: () => undefined,
  },
  disabled: {
    type: Boolean,
    default: false,
  },

  placeholder: {
    type: String,
    default: "请选择地址",
  },
  isShowControl: {
    // 是否显示‘暂时不选得控件’
    type: Boolean,
    default: true,
  },
});

其中isShowControl,用于控制暂不选择的功能节点

3.数据回显

这是关键的一步,需要通过向数据库保存选择的代号,以数组(按分类的顺序)保存,
等获取详情后再通过相应的code去请求默认数据


const onSetDefaultAddress = async (cur) => {
  // address: [],  // 以这个的数量为参考
  // 默认选中的项目
  // select: [], // 这里的数量只会比address少于或等于

  if (cur) {
    const arr = [];
    cur.address.forEach((item, itemIndex) => {
      if (itemIndex === 0) {
        // countryDatas.value = item;
        arr.push(onGetRegion(undefined, "country"));
      } else if (itemIndex === 1) {
        // provinceDatas.value = item;
        arr.push(onGetRegion(cur.address[itemIndex - 1], "province"));
      } else if (itemIndex === 2) {
        // cityDatas.value = item;
        arr.push(onGetRegion(cur.address[itemIndex - 1], "city"));
      } else if (itemIndex === 3) {
        // areaDatas.value = item;
        arr.push(onGetRegion(cur.address[itemIndex - 1], "area"));
      }
    });
    await Promise.all(arr);

    cur.select.forEach((item, itemIndex) => {
      if (itemIndex === 0) {
        countryActiveItem.value = item;
      } else if (itemIndex === 1) {
        provinceActiveItem.value = item;
      } else if (itemIndex === 2) {
        cityActiveItem.value = item;
      } else if (itemIndex === 3) {
        areaActiveItem.value = item;
      }
    });
    currentTopActive.value = "country"; // 默认跳回国家
    autoAddressText(); // 显示文本信息
  } else {
    initData();
    onGetRegion(undefined, "country");
  }
};

代码中的onGetRegion就是接口定义中的接口调用方法

autoAddressText用于自动拼凑回显

大致的思路就如上面所述,供大家参考!也对自己开发过程的一次总结

相关文章
|
14天前
|
JavaScript 前端开发 UED
Vue与uni-app开发中通过@font-face巧妙引入自定义字体
Vue与uni-app开发中通过@font-face巧妙引入自定义字体
35 9
|
17天前
|
缓存 小程序 索引
uni-app开发微信小程序时vant组件van-tabs的使用陷阱及解决方案
uni-app开发微信小程序时vant组件van-tabs的使用陷阱及解决方案
102 1
|
18天前
|
存储 API 数据库
uniapp APP自动更新组件
uniapp APP自动更新组件
41 1
|
13天前
|
JavaScript 小程序 开发者
uni-app开发实战:利用Vue混入(mixin)实现微信小程序全局分享功能,一键发送给朋友、分享到朋友圈、复制链接
uni-app开发实战:利用Vue混入(mixin)实现微信小程序全局分享功能,一键发送给朋友、分享到朋友圈、复制链接
143 0
|
20天前
|
存储 前端开发 UED
uni-app:基础组件 (下)
本文介绍了多种前端组件及其用法,包括:label 组件用于表单元素的标签;picker 组件用于实现日期、时间及普通列表的选择器;textarea 组件用于输入多行文本,并可通过 v-model 双向绑定数据;process 组件用于显示进度条;swiper 组件用于轮播图展示;match-media 组件根据屏幕尺寸展示内容;audio 组件用于播放音频;switch 组件用于开关选择;scroll-view 组件实现滚动视图功能;以及 storage 的使用方法,如设置、获取和移除本地存储等。
|
20天前
|
存储 前端开发 JavaScript
uni-app:基础组件 (上)
本文介绍了uni-app中多个组件的使用方法,包括存储操作、图标展示、按钮样式、表单输入、导航跳转和输入框控制等。通过具体代码示例展示了如何设置存储键值、使用不同类型的按钮、实现表单提交与重置功能、控制输入框的显示与清除等功能。
|
2月前
|
移动开发 小程序 前端开发
uni-app组件样式修改不生效
uni-app组件样式修改不生效
|
3月前
|
存储 BI Android开发
全开源仿第八区H5APP封装打包分发系统源码
全开源仿第八区H5APP封装打包分发系统源码
123 4
|
3月前
|
XML 数据格式
【Azure Logic App】在Logic App中使用 Transfer XML组件遇见错误 undefined
【Azure Logic App】在Logic App中使用 Transfer XML组件遇见错误 undefined
|
3月前
|
JavaScript Linux 应用服务中间件
【Azure 应用服务】FTP 部署 Vue 生成的静态文件至 Linux App Service 后,访问App Service URL依旧显示Azure默认页面问题
【Azure 应用服务】FTP 部署 Vue 生成的静态文件至 Linux App Service 后,访问App Service URL依旧显示Azure默认页面问题