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


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对象和DOM对象的相互转化实现代码
Mar 02 Javascript
ExtJs扩展之GroupPropertyGrid代码
Mar 05 Javascript
原生javascript实现简单的datagrid数据表格
Jan 02 Javascript
基于JS实现textarea中获取动态剩余字数的方法
May 25 Javascript
ES6新特性五:Set与Map的数据结构实例分析
Apr 21 Javascript
nginx部署访问vue-cli搭建的项目的方法
Feb 12 Javascript
使用Vue自定义指令实现Select组件
May 24 Javascript
javascript显示动态时间的方法汇总
Jul 06 Javascript
vue.js添加一些触摸事件以及安装fastclick的实例
Aug 28 Javascript
ajax与jsonp的区别及用法
Oct 16 Javascript
vue 实现滚动到底部翻页效果(pc端)
Jul 31 Javascript
VuePress 中如何增加用户登录功能
Nov 29 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.ini中添加extension=php_mysqli.dll指令的说明
2007/06/14 PHP
PHPLog php 程序调试追踪工具
2009/09/09 PHP
zf框架的registry(注册表)使用示例
2014/03/13 PHP
php命令行(cli)模式下报require 加载路径错误的解决方法
2015/11/23 PHP
解决form中action属性后面?传递参数 获取不到的问题
2017/07/21 PHP
一样的table?不一样的table(可编辑状态table)
2012/09/19 Javascript
关于JS判断图片是否加载完成且获取图片宽度的方法
2013/04/09 Javascript
Jquery取得iframe下内容的方法
2013/11/18 Javascript
javascript动态向网页中添加表格实现代码
2014/02/19 Javascript
JS案例分享之金额小写转大写
2014/05/15 Javascript
jquery ajax请求方式与提示用户正在处理请稍等
2014/09/01 Javascript
TypeError document.getElementById(...) is null错误原因
2015/05/18 Javascript
Bootstrap组件学习之导航、标签、面包屑导航(精品)
2016/05/17 Javascript
Vue.js每天必学之过滤器与自定义过滤器
2016/09/07 Javascript
JS控制div跳转到指定的位置的几种解决方案总结
2016/11/05 Javascript
ES6正则的扩展实例详解
2017/04/25 Javascript
JQuery 封装 Ajax 常用方法(推荐)
2017/05/21 jQuery
vue elementUI使用tabs与导航栏联动
2019/06/21 Javascript
[01:35]2018完美盛典章节片——共竞
2018/12/17 DOTA
python中字典(Dictionary)用法实例详解
2015/05/30 Python
python中如何正确使用正则表达式的详细模式(Verbose mode expression)
2017/11/08 Python
python登录并爬取淘宝信息代码示例
2017/12/09 Python
python 接口返回的json字符串实例
2018/03/27 Python
Python清空文件并替换内容的实例
2018/10/22 Python
对pandas中时间窗函数rolling的使用详解
2018/11/28 Python
Python+OpenCV图像处理—— 色彩空间转换
2020/10/22 Python
html通过canvas转成base64的方法
2019/07/18 HTML / CSS
人力管理专业毕业生求职信
2014/02/27 职场文书
教师党员群众路线教育实践活动心得体会
2014/11/04 职场文书
2015新学期家长寄语
2015/02/26 职场文书
2015毕业生自我评价范文
2015/03/02 职场文书
银行安全保卫工作总结
2015/08/10 职场文书
2015年小学语文教师工作总结
2015/10/23 职场文书
Golang实现AES对称加密的过程详解
2021/05/20 Golang
一文读懂navicat for mysql基础知识
2021/05/31 MySQL
讲解MySQL增删改操作
2022/05/06 MySQL