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


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 相关文章推荐
html中使用javascript调用本地程序(exe、doc等)实现代码
Apr 26 Javascript
浮动的div自适应居中显示的js代码
Dec 23 Javascript
jQuery删除节点的三个方法即remove()detach()和empty()
Dec 27 Javascript
js实现的倒计时按钮实例
Jun 24 Javascript
javascript实现方法调用与方法触发小结
Mar 26 Javascript
深入理解bootstrap框架之入门准备
Oct 09 Javascript
TypeScript学习之强制类型的转换
Dec 27 Javascript
jQuery插件zTree实现更新根节点中第i个节点名称的方法示例
Mar 08 Javascript
js数组常用最重要的方法
Feb 04 Javascript
vue项目webpack中Npm传递参数配置不同域名接口
Jun 15 Javascript
jQuery实现的网站banner图片无缝轮播效果完整实例
Jan 28 jQuery
解决VUE项目localhost端口服务器拒绝连接,只能用127.0.0.1的问题
Aug 14 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
php UBB 解析实现代码
2011/11/27 PHP
PHP转换文本框内容为HTML格式的方法
2016/07/20 PHP
thinkPHP5.0框架安装教程
2017/03/25 PHP
php处理多图上传压缩代码功能
2018/06/13 PHP
用Jquery实现可编辑表格并用AJAX提交到服务器修改数据
2009/12/27 Javascript
用AJAX返回HTML片段中的JavaScript脚本
2010/01/04 Javascript
js jquery验证银行卡号信息正则学习
2013/01/21 Javascript
用js代码改变单选框选中状态的简单实例
2013/12/18 Javascript
JavaScript中string对象
2015/06/12 Javascript
jQuery平滑旋转幻灯片特效代码分享
2015/09/07 Javascript
全面解析Bootstrap表单使用方法(表单样式)
2015/11/24 Javascript
JavaScript希尔排序、快速排序、归并排序算法
2016/05/08 Javascript
JavaScript作用域示例详解
2016/07/07 Javascript
JavaScript递归函数解“汉诺塔”算法代码解析
2018/07/05 Javascript
vue中使用echarts制作圆环图的实例代码
2018/07/27 Javascript
js实现图片实时时钟
2020/01/15 Javascript
解决vue 给window添加和移除resize事件遇到的坑
2020/07/21 Javascript
vue项目中使用多选框的实例代码
2020/07/22 Javascript
JS代码实现页面切换效果
2021/01/10 Javascript
详解Python的Django框架中Manager方法的使用
2015/07/21 Python
Python2随机数列生成器简单实例
2017/09/04 Python
基于Django的python验证码(实例讲解)
2017/10/23 Python
Python编写Windows Service服务程序
2018/01/04 Python
python如何实现int函数的方法示例
2018/02/19 Python
python函数式编程学习之yield表达式形式详解
2018/03/25 Python
详解Python多线程下的list
2020/07/03 Python
python中Array和DataFrame相互转换的实例讲解
2021/02/03 Python
python装饰器代码深入讲解
2021/03/01 Python
来自美国主售篮球鞋的零售商店:KICKSUSA
2017/11/28 全球购物
KELLER SPORTS荷兰:在线订购最好的运动产品
2020/10/13 全球购物
《记承天寺夜游》教学反思
2014/02/16 职场文书
市场营销策划方案
2014/06/11 职场文书
2014广电局实施党的群众路线教育实践活动方案思想汇报
2014/09/22 职场文书
公务员考察材料
2014/12/23 职场文书
职工年度考核评语
2014/12/31 职场文书
工厂清洁工岗位职责
2015/02/14 职场文书