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


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 相关文章推荐
javascript之querySelector和querySelectorAll使用说明
Oct 09 Javascript
JS 实现Json查询的方法实例
Apr 12 Javascript
js变换显示图片的实例
Apr 16 Javascript
javascript 用函数语句和表达式定义函数的区别详解
Jan 06 Javascript
jQuery源码解读之hasClass()方法分析
Feb 20 Javascript
JS实现的通用表单验证插件完整实例
Aug 20 Javascript
全面解析Bootstrap中nav、collapse的使用方法
May 22 Javascript
JS实现微信摇一摇原理解析
Jul 22 Javascript
js实现简易聊天对话框
Aug 17 Javascript
Layui Form 自定义验证的实例代码
Sep 14 Javascript
Vue3配置axios跨域实现过程解析
Nov 25 Vue.js
JavaScript 生成唯一ID的几种方式
Feb 19 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
ThinkPHP令牌验证实例
2014/06/18 PHP
php 无限级分类,超级简单的无限级分类,支持输出树状图
2014/06/29 PHP
php获取一定范围内取N个不重复的随机数
2016/05/28 PHP
php post json参数的传递和接收处理方法
2018/05/31 PHP
Aster vs Newbee BO3 第二场2.18
2021/03/10 DOTA
Javascript学习笔记-详解in运算符
2011/09/13 Javascript
浅谈JavaScript之事件绑定
2013/07/08 Javascript
js 操作select与option(示例讲解)
2013/12/20 Javascript
JS 在指定数组中随机取出N个不重复的数据
2014/06/10 Javascript
浅析javascript异步执行函数导致的变量变化问题解决思路
2016/05/13 Javascript
JS Attribute属性操作详解
2016/05/19 Javascript
JS实现重新加载当前页面
2016/11/29 Javascript
微信小程序 下拉菜单的实现
2017/04/06 Javascript
Vue-Router2.X多种路由实现方式总结
2018/02/09 Javascript
详解webpack4多入口、多页面项目构建案例
2018/05/25 Javascript
Nuxt v-bind绑定img src不显示的解决
2019/12/05 Javascript
JS面向对象编程基础篇(一) 对象和构造函数实例详解
2020/03/03 Javascript
AutoJs实现刷宝短视频的思路详解
2020/05/22 Javascript
vue点击按钮实现简单页面的切换
2020/09/08 Javascript
vue-cli3自动消除console.log()的调试信息方式
2020/10/21 Javascript
python获取本地计算机名字的方法
2015/04/29 Python
分享Python开发中要注意的十个小贴士
2016/08/30 Python
Python基于分水岭算法解决走迷宫游戏示例
2017/09/26 Python
django的ORM模型的实现原理
2019/03/04 Python
代码实例讲解python3的编码问题
2019/07/08 Python
为什么称python为胶水语言
2020/06/16 Python
Python基于字典实现switch case函数调用
2020/07/22 Python
Python过滤序列元素的方法
2020/07/31 Python
中国好声音广告词
2014/03/18 职场文书
优秀团员事迹材料1500字
2014/08/31 职场文书
2015羊年春节慰问信
2015/02/14 职场文书
2015年毕业生实习评语
2015/03/25 职场文书
酒店圣诞节活动总结
2015/05/06 职场文书
本科毕业论文致谢怎么写
2015/05/14 职场文书
丧事主持词
2015/07/02 职场文书
angular异步验证器防抖实例详解
2022/03/31 Javascript