小程序自定义组件实现城市选择功能


Posted in Javascript onJuly 18, 2018

上篇文章有介绍一些小程序的自定义组件语法,这篇文章就不多做赘述,重点介绍组件的实现逻辑。

先把效果图贴出来,看看要实现的效果:

小程序自定义组件实现城市选择功能

城市选择效果图.gif

首先还是设置布局,从实现效果看,组件可分成三个部分:展示城市数据的二级列表、侧边的滑动栏以及中间的提示框。也就是一个scroll-view,一个view布局以及一个text。最终确定的wxml布局文件如下:

<scroll-view class='cityList' scroll-y scroll-into-view='{{currentIndex}}' scroll-top='{{scrollTop}}'>
   <view wx:for='{{allCities}}'>
     <view class='letter-class' id="id{{index}}">{{item.letter}}</view>
     <view class='item-class' wx:for='{{item.cityList}}' wx:for-item='cityItem' bindtap='citySelectEvent' data-city='{{cityItem.name}}' data-letter='{{cityItem.key}}'>{{cityItem.name}}</view>
   </view>
</scroll-view>
 
<view class='citySlide' catchtouchstart='slideStart' catchtouchmove='slideMove' catchtouchend='slideEnd'>
   <view class='citySlideItem' wx:for='{{allCities}}' data-index='{{index}}'>{{item.letter}}</view>
</view>
 
<text class='letterText' hidden='{{isLetterHidden}}' style='top:{{letterTop}}px;left:{{letterLeft}}px'>{{letterText}}</text>

布局文件有了,我们就需要考虑该如何实现侧边栏与二级列表的联动效果了。这里我利用的是scroll-view的scroll-into-view属性,这个属性能让scroll-view滑动到对应id的view的位置,很符合我们的需求。

小程序自定义组件实现城市选择功能

scroll-into-view属性.png

这里我们为列表的第一级布局view设置id,并为scroll-view设置scroll-into-view属性

<scroll-view class='cityList' scroll-y scroll-into-view='{{currentIndex}}' scroll-top='{{scrollTop}}'>
  .
  .
  .
//id不能以数字开头
<view class='letter-class' id="id{{index}}">{{item.letter}}</view>

然后在.js中的data中初始化currentIndex为'id0'

/**
   * 组件的初始数据
   */
   data: {
     currentIndex: 'id0'
   }

现在的问题就是如何计算出手指在侧边栏上触摸的是第几个letter,然后通过改变currentIndex的值,使scroll-view滑动到指定位置来达到联动的效果。

下面说下思路

首先确认侧边栏的高度,我是以屏幕高度减去80px作为侧边栏高度,在.wxss文件中通过样式设置。

.citySlide {
   display: flex;
   flex-direction: column;
   width: 60rpx;
   height: calc(100% - 80px);
   position: absolute;
   top: 40px;
   right: 16rpx;
   align-items: center;
   justify-content: center;
   background-color: #ccc;
   opacity: 0.6;
}

然后在.js中通过把屏幕高度减去80px计算出侧边栏的具体高度。再除以数据源的一级数据数组长度,计算出每个letter的高度。

wx.getSystemInfo({
        success: function (res) {
          letterLineHeight = (res.windowHeight - 80) / that.data.allCities.length;
          that.setData({
             letterTop: res.windowHeight / 2 - 30,
             letterLeft: res.windowWidth / 2 - 30
          });
        }
     })

计算出每个letter的高度后,我们就可以在侧边栏的触摸监听事件中,通过触摸的点的坐标位置,来计算出当前触摸的letter的序号index,然后再动态修改currentIndex的值为('id'+index)。就可以达到联动的效果了。

显示在屏幕中央的提示框的实现则比较简单,通过一个变量isLetterHidden控制text的显示与隐藏就可以轻松实现。

slideStart: function (e) {
  //手指触摸的y坐标值
  var touchY = e.touches[0].clientY;
  //布局距离屏幕顶端距离
  var offsetTop = e.currentTarget.offsetTop;
  var index = parseInt((touchY - offsetTop) / letterLineHeight);
  this.setData({
    currentIndex: 'id' + index,
    isLetterHidden: false,
    letterText: this.data.allCities[index].letter
  });
},
 
slideMove: function (e) {
  var touchY = e.touches[0].clientY;
  var offsetTop = e.currentTarget.offsetTop;
  var index = parseInt((touchY - offsetTop) / letterLineHeight);
  this.setData({
    currentIndex: 'id' + index,
    isLetterHidden: false,
    letterText: this.data.allCities[index].letter
  });
},
 
slideEnd: function (e) {
  var that = this;
  wx: setTimeout(function () {
    that.setData({
       isLetterHidden: true
    });
  }, 200);
}

这里有一点要注意,设置侧边栏触摸事件的时候,要选择catchtouchxxxx事件,不能使用bindtouchxxxx,因为bind事件不会阻止事件冒泡,这样手指在侧边栏滑动时,会影响到下方的列表的滑动,而catch事件阻止了事件冒泡,就不会出现滑动影响的问题。

再说下城市的数据源格式要求,要求是一个二维数组,然后子项要有name和key两个字段,分别代表城市名和类别letter。

小程序自定义组件实现城市选择功能

数据源格式.png

项目GitHub地址:TemplateOfHotel

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JQuery 小练习(实例代码)
Aug 07 Javascript
分享精心挑选的12款优秀jQuery Ajax分页插件和教程
Aug 09 Javascript
jQuery验证元素是否为空的两种常用方法
Mar 17 Javascript
javascript判断并获取注册表中可信任站点的方法
Jun 01 Javascript
js仿QQ中对联系人向左滑动、滑出删除按钮的操作
Apr 07 Javascript
JS控制弹出悬浮窗口(一览画面)的实例代码
May 30 Javascript
详解VueJs异步动态加载块
Mar 09 Javascript
Vue Router去掉url中默认的锚点#
Aug 01 Javascript
Vue 第三方字体图标引入 Font Awesome的方法
Sep 28 Javascript
微信小程序实现点赞、取消点赞功能
Nov 02 Javascript
JS判断浏览器类型与操作系统的方法分析
Apr 30 Javascript
Vue项目接入Paypal实现示例详解
Jun 04 Javascript
微信小程序实践之动态控制组件的显示/隐藏功能
Jul 18 #Javascript
微信小程序项目实践之主页tab选项实现
Jul 18 #Javascript
详解性能更优越的小程序图片懒加载方式
Jul 18 #Javascript
微信小程序项目实践之验证码倒计时功能
Jul 18 #Javascript
微信小程序日期选择器实例代码
Jul 18 #Javascript
JavaScript实现的反序列化json字符串操作示例
Jul 18 #Javascript
Angularjs实现多图片上传预览功能
Jul 18 #Javascript
You might like
第十四节 命名空间 [14]
2006/10/09 PHP
php使浏览器直接下载pdf文件的方法
2013/11/15 PHP
ThinkPHP连接数据库及主从数据库的设置教程
2014/08/22 PHP
PHP将HTML转换成文本的实现代码
2015/01/21 PHP
基于thinkphp6.0的success、error实现方法
2019/11/05 PHP
jQuery-Easyui 1.2 实现多层菜单效果的代码
2012/01/13 Javascript
easyui validatebox验证
2016/04/29 Javascript
jQuery弹出遮罩层效果完整示例
2016/09/13 Javascript
JavaScript定义全局对象的方法示例
2017/01/12 Javascript
微信小程序实现之手势锁功能实例代码
2018/07/19 Javascript
JS实现放烟花效果
2020/03/10 Javascript
jQuery 动态粒子效果示例代码
2020/07/07 jQuery
Python的动态重新封装的教程
2015/04/11 Python
python 容器总结整理
2017/04/04 Python
python中numpy.zeros(np.zeros)的使用方法
2017/11/07 Python
PyQt5实现下载进度条效果
2018/04/19 Python
python邮件发送smtplib使用详解
2020/06/16 Python
教你利用Python玩转histogram直方图的五种方法
2018/07/30 Python
python实现飞机大战
2018/09/11 Python
python中协程实现TCP连接的实例分析
2018/10/14 Python
Pandas过滤dataframe中包含特定字符串的数据方法
2018/11/07 Python
Python实现将通信达.day文件读取为DataFrame
2018/12/22 Python
python实现将列表中各个值快速赋值给多个变量
2020/04/02 Python
浅谈keras保存模型中的save()和save_weights()区别
2020/05/21 Python
pandas创建DataFrame的7种方法小结
2020/06/14 Python
利用CSS3的transition属性实现滑动效果
2015/08/05 HTML / CSS
浅谈HTML5新增及移除的元素
2016/06/27 HTML / CSS
HTML5中的强制下载属性download使用实例解析
2016/05/12 HTML / CSS
static关键字的用法
2013/10/07 面试题
售后服务承诺书怎么写
2014/05/21 职场文书
业绩倒数第一的检讨书
2014/09/24 职场文书
团拜会主持词
2015/07/04 职场文书
六五普法学习心得体会
2016/01/21 职场文书
使用Python脚本对GiteePages进行一键部署的使用说明
2021/05/27 Python
opencv用VS2013调试时用Image Watch插件查看图片
2021/07/26 Python
分布式架构Redis中有哪些数据结构及底层实现原理
2022/03/13 Redis