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


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 相关文章推荐
extjs中grid中嵌入动态combobox的应用
Jan 01 Javascript
jQuery Form 页面表单提交的小例子
Nov 15 Javascript
javascript窗口宽高,鼠标位置,滚动高度(详细解析)
Nov 18 Javascript
JQuery性能优化的几点建议
May 14 Javascript
Jquery对select的增、删、改、查操作
Feb 06 Javascript
使用AngularJS和PHP的Laravel实现单页评论的方法
Jun 19 Javascript
jQuery仿京东商城楼梯式导航定位菜单
Jul 25 Javascript
ionic进入多级目录后隐藏底部导航栏(tabs)的完美解决方案
Nov 23 Javascript
Vue中正确使用jQuery的方法
Oct 30 jQuery
浅析Vue下的components模板使用及应用
Nov 27 Javascript
vue-model实现简易计算器
Aug 17 Javascript
JavaScript中展开运算符及应用的实例代码
Jan 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中文件上传的安全问题
2006/10/09 PHP
PHP表单递交控件名称含有点号(.)会被转化为下划线(_)的处理方法
2013/01/06 PHP
php指定函数参数默认值示例代码
2013/12/04 PHP
百度地图API应用之获取用户的具体位置
2014/06/10 PHP
PHP面试题之文件目录操作
2015/10/15 PHP
IIS 7.5 asp Session超时时间设置方法
2017/04/17 PHP
用js生产批量批处理执行命令
2008/07/28 Javascript
国外大牛IE版本检测!现在IE都到9了,IE检测代码
2012/01/04 Javascript
JS 屏蔽键盘不可用与鼠标右键不可用的方法
2013/11/18 Javascript
js中substring和substr的定义和用法
2014/05/05 Javascript
JavaScript实现将文本框的值插入指定位置的方法
2015/08/13 Javascript
JavaScript使用DeviceOne开发实战(四)仿优酷视频应用
2015/12/02 Javascript
jQuery检测滚动条是否到达底部
2015/12/15 Javascript
js确认框confirm()用法实例详解
2016/01/07 Javascript
基于javascript实现彩票随机数生成(简单版)
2020/04/17 Javascript
AngularJS模块详解及示例代码
2016/08/17 Javascript
BootStrap点击保存后实现模态框自动关闭的思路(模态框)
2017/09/26 Javascript
JS实现的将html转为pdf功能【基于浏览器端插件jsPDF】
2018/02/06 Javascript
使用react实现手机号的数据同步显示功能的示例代码
2018/04/03 Javascript
了解ESlint和其相关操作小结
2018/05/21 Javascript
vue源码学习之Object.defineProperty 对数组监听
2018/05/30 Javascript
python通过BF算法实现关键词匹配的方法
2015/03/13 Python
Flask框架中request、请求钩子、上下文用法分析
2019/07/23 Python
感知器基础原理及python实现过程详解
2019/09/30 Python
Python re正则表达式元字符分组()用法分享
2020/02/10 Python
漫威玩具服装及周边商品官方购物网站:Marvel Shop
2019/05/11 全球购物
简单租房协议书
2014/04/09 职场文书
党员自我剖析材料
2014/08/31 职场文书
学党史心得体会
2014/09/05 职场文书
完整版商业计划书
2014/09/15 职场文书
银行稽核岗位职责
2015/04/13 职场文书
广播体操比赛主持词
2015/06/29 职场文书
三八节活动简报
2015/07/20 职场文书
导游词之淮安明祖陵
2019/11/25 职场文书
2021-4-3课程——SQL Server查询【2】
2021/04/05 SQL Server
python通配符之glob模块的使用详解
2021/04/24 Python