utils

import BScroll from '@better-scroll/core'  // BScroll 核心
import MouseWheel from '@better-scroll/mouse-wheel'  // 引入滚轮
import PullDown from '@better-scroll/pull-down'  // 上拉
import Scrollbar from '@better-scroll/scroll-bar'BScroll.use(MouseWheel)  // 下载滚轮插件
BScroll.use(PullDown)  // 下载上拉
BScroll.use(Scrollbar)const TIME_BOUNCE = 800  // 上拉弹跳时间
const REQUEST_TIME = 1000  // 请求处理时间
const THRESHOLD = 100  // 上拉高度执行
const STOP = 56  // 弹跳高度
let STEP = 0  // 页码// Y轴滚动
export const BS = (wrapper, setBsContainer = false, action = false,) =>
{const { payload } = actionif (wrapper){if (typeof wrapper === 'string'){let wrapperRef = document.querySelector('#' + wrapper)deploy(wrapperRef ? wrapperRef : null, setBsContainer ? setBsContainer : null, payload ? payload.callback : null)} else{deploy(wrapper ? wrapper : null, setBsContainer ? setBsContainer : null, payload ? payload.callback : null)}}
}
// Y轴配置
const deploy = (wrapper, setBsContainer, callback) =>
{let bs = new BScroll(wrapper, {probeType: 3,  // 默认0 不侦测 0和1 都不侦测  2:在手指滚动的过程中侦测 手指离开后的惯性滚动过程中不侦测 3:只要是滚动 都进行侦测click: true,  // 可以点击  用法:要覆盖本机滚动,BetterScroll必须禁止某些默认浏览器行为,例如鼠标单击。如果您希望您的应用程序响应click事件,则必须将该选项显式设置为true。然后BetterScroll将向其_constructed调度事件添加一个私有属性,该属性的值为true。pullDownRefresh: true,  // 向上拉 可以上拉 请求数据 加载更多mouseWheel: true,  // 鼠标滚轮bounceTime: TIME_BOUNCE,  // 上拉弹跳时间pullDownRefresh: {threshold: THRESHOLD,stop: STOP}})if (setBsContainer) setBsContainer(bs)  // 用于保存 bs 对象bs.on('scroll', position =>{if (callback){const { scrolled } = callbackscrolled(position, bs) // 发送两个参数 position 位置  bs 对象}// 默认情况下 BScroll 是不可以实时监听滚动位置// console.log(position); // 实时滚动的位置})bs.on('pullingDown', () =>{// 触发时机:在一次上拉加载的动作后 这个时机一般用来去后端请求数据// bs.finishPullUp()// 注意 只能回调一次console.log('上拉加载更多');// 先去发送网络请求 请求更多页的数据// 等数据请求完成 并将数据展示出来setTimeout(() =>{bs.finishPullDown()  // 再次下拉if (callback){const PullBack = [TIME_BOUNCE, REQUEST_TIME, THRESHOLD, STOP, STEP]const { pullUp } = callbackpullUp(PullBack, '上拉后发送的数据')}// bs.refresh()// bs.finishPullUp()   // 可以再次执行}, 1500)  // 两秒拉一次})bs.on('scrollEnd', e =>{console.log('滚动结束');})
}// X轴滚动 container 两个参数 一个 wrapper 一个滚动条的 ref  setDsContainer 用来保存 DS action 暂时没写
export const DS = (container, setDsContainer = false, action = false) =>
{const { wrapper, scrollBar } = container  // wrapper 可以是 id scrollBar 必须是 Refconst { payload } = actionconsole.log(wrapper, 'data');if (wrapper){if (typeof wrapper === 'string'){let wrapperRef = document.querySelector('#' + wrapper)deployX(wrapper ? [wrapperRef, scrollBar] : null, setDsContainer ? setDsContainer : null, payload ? payload.callback : null)} else{deployX(wrapper ? [wrapper, scrollBar] : null, setDsContainer ? setDsContainer : null, payload ? payload.callback : null)}}
}
// X轴配置
const deployX = (container, setDsContainer) =>  // horizontal 拿到自定义滚动条 ref
{let [wrapper, horizontal] = container  // 结构赋值if (wrapper){let ds = new BScroll(wrapper, {probeType: 0,  // 默认0 不侦测 0和1 都不侦测  2:在手指滚动的过程中侦测 手指离开后的惯性滚动过程中不侦测 3:只要是滚动 都进行侦测click: true,  // 可以点击  用法:要覆盖本机滚动,BetterScroll必须禁止某些默认浏览器行为,例如鼠标单击。如果您希望您的应用程序响应click事件,则必须将该选项显式设置为true。然后BetterScroll将向其_constructed调度事件添加一个私有属性,该属性的值为true。mouseWheel: true,  // 鼠标滚轮scrollX: true,scrollY: false,scrollbar: {customElements: [horizontal],  // 自定义滚动条  [horizontal,vertical]  横竖 我只用了 horizontal 滚动条 DOM 传过来的 REFfade: true,  // 淡入淡出interactive: true,scrollbarTrackClickable: true}  // 滚动条})setDsContainer(ds)  // 保存 ds}
}// 防抖函数
export const debounce = (func, delay) =>
{let timer = null;return function (...args){if (timer) clearTimeout(timer);timer = setTimeout(() =>{func.apply(this, args);}, delay);};
}

JS

import React, { useRef, useEffect, useState, Fragment } from 'react'
import styles from './style.less'
import { BS, DS, debounce } from './utils/index'
import { Select } from 'antd';
const { Option } = Select
const index = () =>
{const [rollingArea, setRollingArea] = useState(0)  // 滚动位置const [bsContainer, setBsContainer] = useState(null)  // 保存 BSconst [dsContainer, setDsContainer] = useState(null)  // 保存 DSconst [beforePullDown, setBeforePullDown] = useState(true) // 正在加载中 ~const [isPullingDown, setIsPullingDown] = useState(false)  // 加载完成const [selectName, setSelectName] = useState('yus')const scrollRef = useRef()  // X轴滚动const scrollRefX = useRef()  // Y轴滚动const scrollBar = useRef()  // 滚动条useEffect(() =>{  // 发送数据请求 设置订阅/启动定时器 手动更改 DOM 等 ~  // scrolled 记录滚动  pullUp 记录上拉BS('wrapper', setBsContainer, { payload: { params: null, callback: { scrolled, pullUp } } })  // 传递三个参数 DOM节点、用于保存 BS 对象、 payload:传递一个 params 暂时没作用 callback 用于 接收传递过来的值// BS(scrollRef.current)  // 发送 Ref 也可以发送 DOM 节点  BS('wrapper')DS({ wrapper: 'wrapperX', scrollBar: scrollBar.current }, setDsContainer)// DS({ wrapper: scrollRefX.current, scrollBar: scrollBar.current }, setDsContainer)return () =>{  // 组件卸载之前 做一些收尾工作 比如清楚定时器/取消订阅 等 ~}}, [])  // 检测数组内变量 如果为空 则监控全局// 如果有数据请求 下拉再次请求const requestData = () =>{console.log('请求数据了');}// 滚动事件const scrolled = debounce((roll, bs) =>{  // roll 滚动位置 bs BScroll 对象const { x, y } = roll  // x y 轴的距离// bs && bs.refresh()  //  按钮因为没有写到 content 也就不会影响到滚动的高度 所以也就不需要加 refreshsetRollingArea(y)  // 保存 Y 轴位置}, 100)  // 展示的慢 因为加了防抖函数const pullUp = async (data, news) =>{// console.log(news, '接收你发来的消息');setBeforePullDown(false)  // 更换上拉 顶部展示setIsPullingDown(true)// 如果有请求数据的话 页码加1 page += 1await requestData()  // 因为没有发送网络请求 就包了一个 定时器 有网络请求则不需要setTimeout(() =>{setBeforePullDown(true)setIsPullingDown(false)}, 500)}// 点击到指定区域const btnClick = debounce(() =>{console.log(dsContainer, 'dsContainer');bsContainer.scrollTo(200, -1000, 2000)  // X轴 Y轴 时间 dsContainer.scrollTo(-400, 0, 2000)  // 控制 X 轴滚动// dsContainer.scrollBy(400, 0, 2000)  // 控制 X 轴滚动条}, 1000)// 返回顶部const btnBack = () =>{bsContainer.scrollTo(750, 0, 2000)  // X轴 Y轴 时间 dsContainer.scrollTo(0, -40, 2000)  // 控制 X 轴滚动}// Dom listconst scrollList = () =>{return (<Fragment><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div><div>9</div><div>10</div><div>11</div><div>12</div><div>13</div><div>14</div><div>15</div><div>16</div><div>17</div><div>18</div><div>19</div><div>20</div><div>21</div><div>22</div><div>23</div><div>24</div><div>25</div><div>26</div><div>27</div><div>28</div><div>29</div><div>30</div><div>31</div><div>32</div><div>33</div><div>34</div><div>35</div><div>36</div><div>37</div><div>38</div><div>39</div><div>40</div><div>41</div><div>42</div><div>43</div><div>44</div><div>45</div><div>46</div><div>47</div><div>48</div><div>49</div><div>50</div><div>51</div><div>52</div><div>53</div><div>54</div><div>55</div><div>56</div><div>57</div><div>58</div><div>59</div><div>60</div><div>61</div><div>62</div><div>63</div><div>64</div><div>65</div><div>66</div><div>67</div><div>68</div><div>69</div><div>70</div><div>71</div><div>72</div><div>73</div><div>74</div><div>75</div><div>76</div><div>77</div><div>78</div><div>79</div><div>80</div><div>81</div><div>82</div><div>83</div><div>84</div><div>85</div><div>86</div><div>87</div><div>88</div><div>89</div><div>90</div><div>91</div><div>92</div><div>93</div><div>94</div><div>95</div><div>96</div><div>97</div><div>98</div><div>99</div><div>100</div></Fragment>)}// Dom listconst scrollList2 = () =>{return (<Fragment><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div><div>9</div><div>10</div><div>11</div><div>12</div><div>13</div><div>14</div><div>15</div><div>16</div><div>17</div><div>18</div><div>19</div><div>20</div><div>21</div><div>22</div><div>23</div><div>24</div><div>25</div><div>26</div><div>27</div><div>28</div><div>29</div><div>30</div><div>31</div><div>32</div><div>33</div><div>34</div><div>35</div><div>36</div><div>37</div><div>38</div><div>39</div><div>40</div><div>41</div><div>42</div><div>43</div><div>44</div><div>45</div><div>46</div><div>47</div><div>48</div><div>49</div><div>50</div><div>51</div><div>52</div><div>53</div><div>54</div><div>55</div><div>56</div><div>57</div><div>58</div><div>59</div><div>60</div><div>61</div><div>62</div><div>63</div><div>64</div><div>65</div><div>66</div><div>67</div><div>68</div><div>69</div><div>70</div><div>71</div><div>72</div><div>73</div><div>74</div><div>75</div><div>76</div><div>77</div><div>78</div><div>79</div><div>80</div><div>81</div><div>82</div><div>83</div><div>84</div><div>85</div><div>86</div><div>87</div><div>88</div><div>89</div><div>90</div><div>91</div><div>92</div><div>93</div><div>94</div><div>95</div><div>96</div><div>97</div><div>98</div><div>99</div><div>100</div><div>101</div><div>102</div><div>103</div><div>104</div><div>105</div><div>106</div><div>107</div><div>108</div><div>109</div><div>110</div><div>111</div><div>112</div><div>113</div><div>114</div><div>115</div><div>116</div><div>117</div><div>118</div><div>119</div><div>120</div><div>121</div><div>122</div><div>123</div><div>124</div><div>125</div><div>126</div><div>127</div><div>128</div><div>129</div><div>130</div><div>131</div><div>132</div><div>133</div><div>134</div><div>135</div><div>136</div><div>137</div><div>138</div><div>139</div><div>140</div><div>141</div><div>142</div><div>143</div><div>144</div><div>145</div><div>146</div><div>147</div><div>148</div><div>149</div><div>150</div></Fragment>)}const listX = () =>{return (<Fragment><span>羽神天下第一</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span><span>7</span></Fragment>)}const listX2 = () =>{return (<Fragment><span>少主天下第一</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span><span>7</span><span>8</span><span>9</span><span>10</span><span>11</span><span>12</span><span>13</span><span>14</span><span>15</span><span>16</span><span>17</span><span>18</span><span>19</span><span>20</span></Fragment>)}// 下拉框const handleChange = async (value) =>  // 点击下拉框改变了容器高度 则必须要 refresh 刷新容器{await bsContainer.scrollTo(0, 0, 400)  // 会到顶部await dsContainer.scrollTo(0, 0, 200)setSelectName(value)await bsContainer.refresh()await dsContainer.refresh()}return (<div className={styles.container}>{rollingArea <= -1000 ? (<button onClick={btnBack} className={styles.btn} >点击返回顶部</button>) : null}<Select defaultValue={selectName} style={{ width: 120 }} onChange={handleChange}><Option value="yus">羽神</Option><Option value="sz">少主</Option></Select><div id='wrapper' ref={scrollRef} className={styles.wrapper}><div className={styles.content}>{beforePullDown ? <div className={styles.status}>正在加载中~</div> : null}{isPullingDown ? <div className={styles.status}>数据加载成功了哦</div> : null}<button onClick={btnClick}>按钮点击</button>{selectName === 'yus' ? scrollList() : null}{selectName === 'sz' ? scrollList2() : null}</div></div><div ref={scrollRefX} id="wrapperX" className={styles.scrollCoreX}><div className={styles.scrollCoreYContent}>{selectName === 'yus' ? listX() : null}{selectName === 'sz' ? listX2() : null}</div>{/* 自定义滚动条 */}<div ref={scrollBar} className={styles.horizontal_scrollbar}><div className={styles.horizontal_indicator}></div></div></div></div >)
}export default index

CSS

.container {position: relative;width: 100%;height: 100%;.wrapper {position: relative;margin: 0 auto;width: 800px;height: 400px;background-color: pink;overflow: hidden;}
}.status {position: absolute;width: 100%;padding: 20px;box-sizing: border-box;transform: translateY(-100%) translateZ(0);text-align: center;color: #999;
}.btn {position: fixed;top: 100px;right: 600px;z-index: 1;
}// BetterScroll 实现了水平滚动,对 CSS 要求更高。首先,您需要确保包装器不包装,并且内容的显示是内联块。
/*
.scroll-wrapper// ...white-space nowrap
.scroll-content// ...display inline-block
*/.scrollCoreX {white-space: nowrap;margin: 30px auto;width: 600px;height: 200px;background-color: yellow;overflow: hidden;.scrollCoreYContent {display: inline-block;span {display: inline-block;margin: 20px;width: 200px;height: 200px;background-color: burlywood;}}.horizontal_scrollbar {position: absolute;left: 50%;bottom: 10px;width: 100px;height: 7px;border-radius: 5px;transform: translateX(-50%) translateZ(0);background-color: rgb(200, 200, 200, 0.3);.horizontal_indicator {height: 100%;width: 20px;border-radius: 5px;background-color: #db8090;}}
}

react + better_scroll 简单封装相关推荐

  1. Android APP更新下载工具类——简单封装DownloadManager

    几乎所有APP都包含了检查更新功能,更新下载功能的实现方式常用的有两种:1.使用App网络框架的文件下载请求:2.使用自带的DownloadManager类:本文介绍第二种,简单封装一下Downloa ...

  2. 简单封装浏览器 cookie 工具类

    版权声明:本文首发 http://asing1elife.com ,转载请注明出处. https://blog.csdn.net/asing1elife/article/details/8265571 ...

  3. 小程序简单封装 request 请求

    我在这里做了详细的介绍 : 小程序简单封装 request 请求 转载于:https://www.cnblogs.com/biangz/p/9984340.html

  4. 简单封装 HTTP 请求

    2017-2-19 更新到第二版: 源码地址:http://git.oschina.net/sp42/ajaxjs/tree/master/ajaxjs-base/src/com/ajaxjs/net ...

  5. 【JDBC】实现对JDBC 连接的简单封装

    package util;import java.sql.Connection; import java.sql.DriverManager;/**** 实现对JDBC 的封装* @author mq ...

  6. Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池

    前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...

  7. ios开发之使用多文件上传的简单封装最原始的

    ios开发之使用多文件上传的简单封装最原始的 // // ViewController.m // 18-上传多个文件 // // Created by 鲁军 on 2021/2/13. //#impo ...

  8. Spring jdbc 对象Mapper的简单封装

    一般查询实体的时候,都需要这么使用/**      * 根据id查询      *       * @return      */     public Emp queryEmpById(Intege ...

  9. Google图片加载库Glide的简单封装GlideUtils

    Google图片加载库Glide的简单封装GlideUtils  

最新文章

  1. ASPJPEG缩略图生成函数
  2. 曼哈顿距离和切比雪夫距离链接
  3. Android 6.0 7.0 8.0 一个简单的app内更新版本-okgo app版本更新
  4. 监管大屏系统_餐饮公示大屏广告位招商正式启动!
  5. 如何使用Angular rxjs进行优雅限流
  6. 角距离恒星_恒星问卷调查的10倍机器学习生产率
  7. 数据科学 IPython 笔记本 8.5 简单的散点图
  8. 【珍藏版】 200个机器学习 NLP Python 免费相关教程
  9. Ibatis -- 一次执行多条SQL
  10. java篇 之 多态
  11. poj3159 Candies 2012-09-07
  12. 手机测试用例-多媒体测试用例
  13. 坚果云 我的电脑图标_如何删除我的电脑里的坚果云文件夹
  14. 【echarts】柱状图正负值双色
  15. 管理的基础知识都包含哪些内容
  16. VIC Classic 驱动程序
  17. 外部Portal认证系统 对接 华为 H3C 等设备实现 LDAP AD域 网络准入实名认证
  18. 连续系统的动态规划问题
  19. scratch/mblock项目:跑酷闯关(侦测、条件语句、数据与变量的应用)
  20. Ios精品源码,tableview下载视频直播源播放器图片位置3D立体旋转相册屏风动画

热门文章

  1. 深度|SHEIN:长期主义的胜利
  2. 兰州大学22计算机考研初试成绩可以查询了吗?
  3. 浅笑云计算机,才太吉:浅笑云舒
  4. MCGS作为Modbus RTU从站
  5. 《哈利·波特与死亡圣器(上)》BD中英双字无水印高清+1080P 720P蓝光地址
  6. 【淘宝ERP】C#与SQLServer数据库连接
  7. Kinect for Windows SDK开发入门(十):手势识别 上:基本概念
  8. WPF实现贪食蛇小案例
  9. 后疫情时代,用吃增强身体这座“城防工事”
  10. ElasticSearch还能性能调优,涨见识、涨见识了!!!