文章目录
- 序言
- 1、HTML部分
- 2、JavaScript部分(上下左右滑动均触发)
- 3、JavaScript部分(左右滑动触发)
- 4、效果演示
序言
最近在写原生微信小程序项目的时候遇到了左右滑动内容更新数据,同时改变tabBar的高亮效果。于是就写了这篇文章,关于文章的css不再此文章中展示,因为都是公共的自定义类名css,所以通过类名大概就能推敲出css的值了。
1、HTML部分
<view class="font_size_36">
<!-- tabBar选项卡 -->
<view class="dis_r_c">
<view class="grid_c3_230 grid_row_gap_10 grid_column_gap_10">
<view class="border_777" wx:for="{{demoTabBar}}" wx:key="id">
<view class="height_90 line_height_90 text_align_center {{isH===item.id?'color_royalblue':''}}" data-item="{{item}}" catchtap="catchtapTabBar">{{item.title}}</view>
</view>
</view>
</view>
<!-- 内容 -->
<view class="margin_t_26 padding_b_36" bindtouchstart="slideStart" bindtouchmove="slideDirection" bindtouchend="slideEnd">
<view>
<view class="border_777 {{index!==0?'margin_t_16':''}}" wx:for="{{list}}" wx:key="id">
<view class="ellipsis">{{item.title}}</view>
</view>
</view>
</view>
</view>
2、JavaScript部分(上下左右滑动均触发)
第一步:在包裹内容的最外层
HTML标签上定义滑动事件。如果页面同时存在横向滑动的选项卡,最好不要把滑动事件绑定到页面的最外层标签上。上下左右滑动均触发的功能只适合那种类似于看小说的页面,因为看小说要么往左滑,要么往右滑,要么往下滑,要么往上滑,要么斜着滑,页面上除了返回按钮,就没有其它复杂的功能了。所以适合这个上下左右滑动均触发的模式。
bindtouchstart="slideStart":开始滑动。
bindtouchmove="slideDirection":滑动事件,只要滑动就会触发。
bindtouchend="slideEnd":滑动结束,即手指离开屏幕时触发。
等号前面是微信小程序提供的绑定事件的属性,等号后面是自定义的事件名。
第二步:在全局引入页面结构数据,并解构。
第三步:
data中的变量及其作用。
demoTabBar:选项卡数据。
originObjList:源数据对象,存放选项卡对应的所有数据内容。
isH:使用数据id设置选项卡的高亮值。
list:存储渲染列表的数据,也就是在切换选项卡时获取对应的数据值。
startX:开始滑动的X轴坐标值。
startY:开始滑动的Y轴坐标值。
direction:滑动方向,L向左滑,R向右滑。
第四步:页面初始化,定义一个名为
init的函数,并在onLoad生命周期函数中调用init函数来实现页面初始化。在init函数中使用JSON的parse和stringify方法克隆数据,以保证数据的完全分离状态。接着便是初始化赋值,分别是tabBar赋值,originObjList数据源赋值,这个数据包含所有的tabBar类目的数据值;isH赋值,获取tabBar数据第一项的id值;list赋值,通过tabBar的第一项数据id获取newTabBar中对应的值。
第五步:绑定选项卡的点击事件,事件名称为
catchtapTabBar。在选项卡标签上自定名为item的变量来向函数传递值。在函数中通过解构获取点击项的值,获取点击项中的id与源数据匹配选项卡的值,最后把得到的值和id值赋给data中的list和isH两个变量。
第六步:绑定开始滑动事件,事件名称为
slideStart。在函数中通过event获取开始滑动的clientX和clientY的值。最后把值分别赋给data中的startX和startY,这个值也就是开始滑动的坐标值。
第七步:绑定滑动中的事件,事件名称为
slideDirection。在函数中通过event获取实时滑动的坐标值,使用Math中的atan和PI两个方法计算角度,通过角度的变化确定滑动的方向。Math.abs(angle) > 50,50这个值如果越大,方向就越不容易被改变,值越大说明需要滑动更远的距离才能改变方向,同时把方向值赋给data中的direction变量等待滑动结束事件使用。
第八步:绑定滑动结束事件,定义事件名为
slideEnd。在函数中准备好数据,首先判断方向,方向分别使用L和R表示,也就是在滑动函数中改变的方向值。L表示向右滑相当于上一页,R表示向左滑相当于下一页。当方向值为L的时候需要i < tabBarLen - 1,当方向值为R的时候需要i > 0。其中tabBarLen - 1表示已经滑动到tabBar的最后一项,不能再向左滑动了。i > 0表示已经滑到tabBar的第一项,不能再向右滑动了。其中i的值通过findIndex方法和isH获取当前对应tabBar中的下标值,tabBarLen的值就是tabBar数据的长度。如果if判断成立,那么就获取对应的内容赋值给list,并且把isH的值同时更新为当前值。如果if条件不成立,那么就给data中driection变量赋值为空字符串。
const {
globalData: {
jsonData: {
tabBar,
objList
},
showToast
}
} = getApp();
Page({
/**
* 页面的初始数据
*/
data: {
demoTabBar: [],
originObjList: [],
isH: '',
list: [],
startX: 0,
startY: 0,
direction: null
},
// 滑动结束
slideEnd() {
let self = this,
selfData = self.data,
direction = selfData.direction,
tabBar = selfData.demoTabBar,
tabBarLen = tabBar.length,
originObjList = selfData.originObjList,
isH = selfData.isH,
i = tabBar.findIndex(item => item.id === isH),
id = '';
if (direction === 'R' && i > 0) { // 向右滑相当于上一页
i -= 1;
} else if (direction === 'L' && i < tabBarLen - 1) { // 向左滑相当于下一页
i += 1;
} else { // 滑动不成立,清空driection
return self.setData({
direction: ''
});
}
id = tabBar[i].id;
self.setData({
list: originObjList[id],
isH: id
});
},
// 滑动中判断滑动方向
slideDirection({ changedTouches }) {
let self = this,
selfData = self.data,
// 开始x坐标
startX = selfData.startX,
// 开始y坐标
startY = selfData.startY,
// 活动变化坐标
touchMoveX = changedTouches[0].clientX,
// 滑动变化坐标
touchMoveY = changedTouches[0].clientY,
direction = '',
_x = touchMoveX - startX,
_Y = touchMoveY - startY,
// Math.atan()返回数据的反正切值
// 这里算的就是角度
angle = 360 * Math.atan(_Y / _X) / (2 * Math.PI);
// 滑动角度超过50retrun
if (Math.abs(angle) > 50) return;
if (touchMoveX > startX) { // 向右滑
direction = 'R';
} else { // 向左滑
direction = 'L';
}
self.setData({
direction
});
},
// 开始滑动
slideStart(e) {
this.setData({
startX: e.changedTouches[0].clientX,
startY: e.changedTouches[0].clientY
})
},
// tabBar选项卡
catchtapTabBar({ currentTarget: { dataset: { item } } }) {
let self = this,
selfData = self.data,
originObjList = selfData.originObjList;
self.setData({
list: originObjList[item.id],
isH: item.id
});
},
// 初始化
init() {
let newTabBar = JSON.parse(JSON.stringify(tabBar)),
originObjList = JSON.parse(JSON.stringify(objList)),
id = newTabBar[0].id;
this.setData({
demoTabBar: newTabBar,
originObjList,
isH: id,
list: originObjList[id]
});
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.init();
},
})
3、JavaScript部分(左右滑动触发)
第一步:这步与上下左右滑动均触发案例的区别就是没有了滑动事件,因为不需要使用滑动事件。
第二步:这步与上下左右滑动均触发案例一样。
第三步:这步
data中的变量与上下左右滑动均触发案例相比少了startX、startY和direction三个变量。同时增加了startPageX变量,这个变量用来记录滑动开始的pageX值,这次获取的不再是clientX的值。
第四步:页面初始化与上下左右滑动均触发案例相同。
第五步:绑定选项卡的点击事件与上下左右滑动均触发案例相同。
第六步:绑定开始滑动事件,事件名称为
slideStart。在函数中通过event获取开始滑动的pageX值,通过parseInt方法舍弃小数部分(这步不是必须,只是个人偏好)。最终把值赋给data中的startPageX变量。
第七步:绑定滑动结束事件,定义事件名为
slideEnd。在函数中准备好数据,i和tabBarLen变量值的获取和作用与上下左右滑动均触发案例相同,这里不再累赘解释。定义endPageX、slidingDistance和direction三个变量,endPageX变量通过解构获取pageX赋值,也就是滑动结束的值,同样需要parseInt方法舍弃小数部分(这步不是必须,只是个人偏好)。slidingDistance变量存储endPageX(滑动结束值)和startPageX(滑动开始值)的差值。direction变量存储方向值,这个方向值是通过获取slidingDistance值的第一个字符决定,如果第一个字符是减号,说明向左滑动,否则向右滑动。if (Math.abs(slidingDistance) < 100) return false;通过Math的abs方法获取slidingDistance变量的绝对值与100比较,如果slidingDistance的值小于100,说明滑动距离太短,通过return中断函数,后续代码不再执行。如果slidingDistance的值大于100,后续代码继续执行,执行逻辑与上下左右滑动均触发案例的第八步类似。
const {
globalData: {
jsonData: {
tabBar,
objList
},
showToast
}
} = getApp();
Page({
/**
* 页面的初始数据
*/
data: {
demoTabBar: [],
originObjList: [],
isH: '',
list: [],
startPageX: 0
},
// 开始滑动
slideStart({ changedTouches }) {
let pageX = changedTouches[0].pageX;
pageX = parseInt(pageX);
this.setData({
startPageX: pageX
});
},
// 滑动结束
slideEnd({ changedTouches }) {
let self = this,
selfData = self.data,
endPageX = changedTouches[0].pageX,
tabBar = selfData.demoTabBar,
tabBarLen = tabBar.length,
originObjList = selfData.originObjList,
isH = selfData.isH,
startPageX = selfData.startPageX,
i = tabBar.findIndex(item => item.id === isH),
id = '',
slidingDistance = 0,
direction = '';
// 滑动结束,并舍弃小数点
endPageX = parseInt(endPageX);
// 滑动距离
slidingDistance = endPageX - startPageX;
// 滑动方向
direction = String(slidingDistance)[0];
if (!Math.abs(slidingDistance) > 100) return false;
if (direction === '-' && i < tabBarLen - 1) { // 向左滑动
i += 1;
} else if (direction !== '-' && i > 0) { // 向右滑动
i -= 1;
} else {
return false;
}
id = tabBar[i].id;
self.setData({
list: originObjList[id],
isH: id
});
},
// tabBar
catchtapTabBar({ currentTarget: { dataset: { item } } }) {
let self = this,
selfData = self.data,
originObjList = selfData.originObjList;
self.setData({
list: originObjList[item.id],
isH: item.id
});
},
// 初始化
init() {
let newTabBar = JSON.parse(JSON.stringify(tabBar)),
originObjList = JSON.parse(JSON.stringify(objList)),
id = newTabBar[0].id;
this.setData({
demoTabBar: newTabBar,
originObjList,
isH: id,
list: originObjList[id]
});
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.init();
}
})



















