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


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访问XML数据的实例
Dec 27 Javascript
javascript css在IE和Firefox中区别分析
Feb 18 Javascript
javascript 表单验证常见正则
Sep 28 Javascript
10个基于jQuery或JavaScript的WYSIWYG 编辑器整理
May 06 Javascript
jquery实现类似EasyUI的页面布局可改变左右的宽度
Sep 12 Javascript
javascript工厂方式定义对象
Dec 26 Javascript
使用jQuery mobile库检测url绝对地址和相对地址的方法
Dec 04 Javascript
AngularJS中的过滤器filter用法完全解析
Apr 22 Javascript
js通过循环多张图片实现动画效果
Dec 19 Javascript
react使用CSS实现react动画功能示例
May 18 Javascript
解决vue 使用setTimeout,离开当前路由setTimeout未销毁的问题
Jul 21 Javascript
vue实现标签云效果的示例
Nov 09 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扩展CURL的用法详解
2014/06/20 PHP
php 魔术方法详解
2014/11/11 PHP
学习php开源项目的源码指南
2014/12/21 PHP
smarty模板引擎之内建函数用法
2015/03/30 PHP
PHP正则表达式过滤html标签属性(DEMO)
2016/05/04 PHP
php计数排序算法的实现代码(附四个实例代码)
2020/03/31 PHP
Javascript的数组与字典用法与遍历对象的属性技巧
2012/11/07 Javascript
form表单只提交数据而不进行页面跳转的解决方案
2013/09/18 Javascript
jquery加载图片时以淡入方式显示的方法
2015/01/14 Javascript
jquery实现红色竖向多级向右展开的导航菜单效果
2015/08/31 Javascript
JS运动相关知识点小结(附弹性运动示例)
2016/01/08 Javascript
js获取鼠标点击的对象,点击另一个按钮删除该对象的实现代码
2016/05/13 Javascript
解决jQuery ajax请求在IE6中莫名中断的问题
2016/06/20 Javascript
JavaScript实现解析INI文件内容的方法
2016/11/17 Javascript
js操作浏览器的参数方法
2017/01/21 Javascript
代码详解Vuejs响应式原理
2017/12/20 Javascript
vue基于element的区间选择组件
2018/09/07 Javascript
详解vuex commit保存数据技巧
2018/12/25 Javascript
Vue组件间通信方法总结(父子组件、兄弟组件及祖先后代组件间)
2019/04/17 Javascript
浅析Vue 防抖与节流的使用
2019/11/14 Javascript
[02:24]DOTA2痛苦女王 英雄基础教程
2013/11/26 DOTA
Python实现导出数据生成excel报表的方法示例
2017/07/12 Python
python将处理好的图像保存到指定目录下的方法
2019/01/10 Python
在django admin中添加自定义视图的例子
2019/07/26 Python
python如何修改文件时间属性
2021/02/05 Python
Bata印度官网:源自欧洲舒适鞋履品牌
2020/01/30 全球购物
PHP经典面试题
2016/09/03 面试题
关于读书的演讲稿400字
2014/08/27 职场文书
党的群众路线教育实践活动个人自我剖析材料
2014/10/07 职场文书
高校自主招生教师推荐信
2015/03/23 职场文书
2015年毕业生个人自荐书
2015/03/24 职场文书
python小程序之飘落的银杏
2021/04/17 Python
PHP设计模式(观察者模式)
2021/07/07 PHP
详解python的异常捕获
2022/03/03 Python
Android在Sqlite3中的应用及多线程使用数据库的建议
2022/04/24 Java/Android
mysql sql常用语句大全
2022/06/21 MySQL