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


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 相关文章推荐
用正则获取指定路径文件的名称
Feb 27 Javascript
JavaScript解析json格式数据简单示例
Dec 09 Javascript
JQuery显示隐藏页面元素的方法总结
Apr 16 Javascript
jquery中trigger()无法触发hover事件的解决方法
May 07 Javascript
JS模拟简易滚动条效果代码(附demo源码)
Apr 05 Javascript
原生JS实现的放大镜效果实例代码
Oct 15 Javascript
layui文件上传实现代码
May 20 Javascript
vue-cli构建项目下使用微信分享功能
May 28 Javascript
微信小程序按钮去除边框线分享页面功能
Aug 27 Javascript
浅谈开发eslint规则
Oct 01 Javascript
JavaScript实现邮箱后缀提示功能的示例代码
Dec 13 Javascript
toString.call()通用的判断数据类型方法示例
Aug 28 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
QueryPath PHP 中的jQuery
2010/04/11 PHP
在php中判断一个请求是ajax请求还是普通请求的方法
2011/06/28 PHP
YII模块实现绑定二级域名的方法
2014/07/09 PHP
PHPUnit安装及使用示例
2014/10/29 PHP
php从文件夹随机读取文件的方法
2015/06/01 PHP
Yii2.0使用阿里云OSS的SDK上传图片、下载、删除图片示例
2017/09/20 PHP
php对微信支付回调处理的方法
2018/08/23 PHP
jQuery select操作控制方法小结
2010/05/26 Javascript
Jquery + Ajax调用webService实例代码(asp.net)
2010/08/27 Javascript
深入Javascript函数、递归与闭包(执行环境、变量对象与作用域链)使用详解
2013/05/08 Javascript
js获取某月的最后一天日期的简单实例
2013/06/22 Javascript
alert出数组中的随即值代码
2014/09/25 Javascript
js简单设置与使用cookie的方法
2016/01/22 Javascript
Vue.js教程之计算属性
2016/11/11 Javascript
表格展示利器 Bootstrap Table实例代码
2017/09/06 Javascript
利用vue.js实现被选中状态的改变方法
2018/02/08 Javascript
使用Three.js实现太阳系八大行星的自转公转示例代码
2019/04/09 Javascript
解决 viewer.js 动态更新图片导致无法预览的问题
2019/05/14 Javascript
新手如何快速理解js异步编程
2019/06/24 Javascript
解决vue路由name同名,路由重复的问题
2020/08/05 Javascript
vue 页面跳转的实现方式
2021/01/12 Vue.js
Python高斯消除矩阵
2019/01/02 Python
python执行scp命令拷贝文件及文件夹到远程主机的目录方法
2019/07/08 Python
利用pyshp包给shapefile文件添加字段的实例
2019/12/06 Python
Python Tkinter实例——模拟掷骰子
2020/10/24 Python
马来西亚网上购物:Youbeli
2018/03/30 全球购物
意大利在线药房:shop-farmacia.it
2019/03/12 全球购物
动漫专业高职生职业生涯规划书
2014/02/15 职场文书
大学军训感言1000字
2014/02/25 职场文书
《狼》教学反思
2014/03/02 职场文书
美容院经理岗位职责
2014/04/03 职场文书
医生个人自我剖析材料
2014/10/08 职场文书
公司搬迁通知
2015/04/20 职场文书
2015年小学数学教师工作总结
2015/05/20 职场文书
《1942》观后感
2015/06/08 职场文书
PyTorch 如何设置随机数种子使结果可复现
2021/05/12 Python