在react中使用better-scroll滚动插件最近公司使用react项目中有一些滚动的效果需要有一些插件来支持,比如iScroll,或者react-scroll,最后还是选择了better-scroll文档比较友好。
进入正题:首先当然是npm安装啦
npm install better-scroll --save
安装完成后开始使用首先在要用到的组件引入better-scroll
import BScroll from 'better-scroll'
准备工作完成首先在render里写下官方定义的DOM
<div class="wrapper"> <ul class="content"> <li>...</li> <li>...</li> ... </ul> <!-- 这里可以放一些其它的 DOM,但不会影响滚动 --> </div>
在生命周期里进行初始实例化
componentDidMount() { const wrapper = document.querySelector('.wrapper') //选中DOM中定义的 .wrapper 进行初始化 const scroll = new BScroll(wrapper, { scrollX: true, //开启横向滚动 click: true, // better-scroll 默认会阻止浏览器的原生 click 事件 scrollY: false, //关闭竖向滚动 }) }
切记不可以在render里进行实例化因为在第一次触发render的时候DOM还未生成所以需要在componentDidMount里进行。滚动原理
很多人已经用过 better-scroll,但是最多的问题是:
better-scroll 初始化了, 但是没法滚动。
不能滚动是现象,我们得搞清楚这其中的根本原因。在这之前,我们先来看一下浏览器的滚动原理: 浏览器的滚动条大家都会遇到,当页面内容的高度超过视口高度的时候,会出现纵向滚动条;当页面内容的宽度超过视口宽度的时候,会出现横向滚动条。也就是当我们的视口展示不下内容的时候,会通过滚动条的方式让用户滚动屏幕看到剩余的内容。
better-scroll 也是一样的原理,我们可以用一张图更直观的感受一下:
布局
绿色部分为 wrapper,也就是父容器,它会有固定的高度。黄色部分为 content,它是父容器的第一个子元素,它的高度会随着内容的大小而撑高。那么,当 content 的高度不超过父容器的高度,是不能滚动的,而它一旦超过了父容器的高度,我们就可以滚动内容区了,这就是 better-scroll 的滚动原理。
完成后就开始css以及style了
<div className="wrapper"> <ul className="content" style={{ width: `${210 * _flattenDeep(list).length}px` }}> { _map(_flattenDeep(list), (v, i) => { return ( <li className="scroll_prod" key={i}> <img src={v.img} /> <div>{v.product}</div> </li> ) }) } </ul> </div>
这里实例是横行滚动因为看到关于解决better-scroll横向滚动的问题的帖子较荒。首先需要给wrapper设置css
.wrapper{ width: 100%; white-space: nowrap; //让子元素超出不换行 padding: 25px 13px; overflow: hidden; }
content元素需要设置动态的width,可以去估算出每个元素的宽度
<ul className="content" style={{ width: `${210 * _flattenDeep(list).length}px` }} > </ul>
在这里我根据数组元素的length来置换ul的总宽度然后就可以滚动啦!当然要是需要竖向滚动需要设置在初始化时
componentDidMount() { const wrapper = document.querySelector('.wrapper') //选中DOM中定义的 .wrapper 进行初始化 const scroll = new BScroll(wrapper, { click: true, // better-scroll 默认会阻止浏览器的原生 click 事件 scrollY: true, //关闭竖向滚动 }) }
开启scrollY配置。
结言:当然better-scroll不只是这两个API官网有很多更好用的API可以根据官网操作(http://ustbhuangyi.github.io/better-scroll/doc/zh-hans/)如果要操作实例上面的方法的话固然在componentDidMount函数里是访问不到已经实例化的BScroll的,所以我们可以将实例挂载到state中。
import BScroll from 'better-scroll' class Commodity extends Component { constructor(props) { super(props) this.state = { Bscroll: '', } } componentDidMount() { const wrapper = document.querySelector('.wrapper') const scroll = new BScroll(wrapper, { scrollX: true, click: true, scrollY: false, }) this.setState({ Bscroll: scroll, }) } render() { const { Bscroll } = this.state render(){ return( <> <div className="wrapper"> <ul className="content" style={{ width: `${210 * _flattenDeep(list).length}px` }}> { _map(_flattenDeep(list), (v, i) => { return ( <li className="scroll_prod" key={i}> <img src={v.img} /> <div>{v.product}</div> <a className="buy">立即购买</a> </li> ) }) } </ul> </div> </> ) }