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


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 相关文章推荐
写了一个layout,拖动条连贯,内容区可为iframe
Aug 19 Javascript
js 操作select相关方法函数
Dec 06 Javascript
js获取select标签的值且兼容IE与firefox
Dec 30 Javascript
js跳转页面方法总结
Jan 29 Javascript
jquery实现的鼠标拖动排序Li或Table
May 04 Javascript
JavaScript函数获取事件源的小例子
May 14 Javascript
node.js中的http.response.write方法使用说明
Dec 14 Javascript
JS实现兼容各浏览器解析XML文档数据的方法
Jun 01 Javascript
实现高性能JavaScript之执行与加载
Jan 30 Javascript
AngularJS动态绑定HTML的方法分析
Nov 07 Javascript
jQuery学习笔记之入门
Dec 14 Javascript
vue-router 权限控制的示例代码
Sep 21 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 session 预定义数组
2009/03/16 PHP
Windows下的PHP 5.3.x安装 Zend Guard Loader教程
2014/09/06 PHP
PHP简单实现上一页下一页功能示例
2016/09/14 PHP
Laravel 将数据表的数据导出,并生成seeds种子文件的方法
2019/10/09 PHP
javascript 动态添加表格行
2006/06/22 Javascript
jQuery EasyUI 的EasyLoader功能介绍
2010/09/12 Javascript
js中文逗号转英文实现
2014/02/11 Javascript
JavaScript极简入门教程(一):基础篇
2014/10/25 Javascript
babel基本使用详解
2017/02/17 Javascript
layui前段框架日期控件使用方法详解
2017/05/19 Javascript
vue-cli如何添加less 以及sass
2017/07/06 Javascript
jquery实现图片跟随鼠标的实例
2017/10/17 jQuery
React操作真实DOM实现动态吸底部的示例
2017/10/23 Javascript
详解webpack-dev-server使用方法
2018/09/14 Javascript
layui输入框中只允许输入整数的实现方法
2019/09/18 Javascript
Vue-Cli项目优化操作的实现
2019/10/27 Javascript
python 从远程服务器下载东西的代码
2013/02/10 Python
python中list列表的高级函数
2016/05/17 Python
Python算法应用实战之栈详解
2017/02/04 Python
python3大文件解压和基本操作
2017/12/15 Python
Django models filter筛选条件详解
2020/03/16 Python
Python ini文件常用操作方法解析
2020/04/26 Python
Python调用jar包方法实现过程解析
2020/08/11 Python
美国摄影爱好者购物网站:Focus Camera
2016/10/21 全球购物
Origins加拿大官网:雅诗兰黛集团高端植物护肤品牌
2017/11/19 全球购物
世界上最好的精品店:Shoptiques
2018/02/05 全球购物
俄罗斯大型在线书店:Читай-город
2019/10/10 全球购物
亚洲最大的运动鞋寄售店:KicksCrew
2020/11/26 全球购物
2014年迎新年联欢会活动策划方案
2014/02/26 职场文书
合伙协议书范本
2014/04/21 职场文书
我爱我的祖国演讲稿
2014/05/04 职场文书
经济贸易专业自荐信
2014/06/11 职场文书
领导班子党的群众路线教育实践活动对照检查材料
2014/09/25 职场文书
2014年工程部工作总结
2014/11/25 职场文书
学校体育节班级口号
2015/12/25 职场文书
css常用字体属性与背景属性介绍
2022/02/28 HTML / CSS