React 初探(十四)
2019-02-18 本文已影响17人
bowen_wu
概述
接下来我们将要完成 Home
页面。Home
页面主要有两个点
- 使用
react-sticky
-
ant-design-mobile
的Modal
组件的背景滚动问题
Home
页面 UI
Home UI
Home
页面功能
- 点击头像去往个人中心页面
- 页面可以滚动,滚动的时候 searchBar 会 sticky 顶部
- 可以通过事件 title 进行搜索
- 点击右下方的 + 可以去往创建 TODO 页面
react-sticky
Home
页面主要使用了 ant-design-mobile
的 ListView
组件,其中借助 react-sticky
将搜索栏在滚动的过程中 sticky 在顶部。这里有官方例子和一些使用方法
ant-design-mobile
的 Modal
组件的背景滚动问题
这个主要是一个在 IOS 下的问题,当页面可以滚动时,有 Modal
显示的时候,此时滚动页面,Modal
后的页面会跟着滚动。ant-design-mobile
有在文档中说明解决方法,但是我在实践的过程中发现并不能解决。所以又搜索了一下,找到了一个可以解决的方法。
ant-design-mobile 解决方法
- 定义一个
closet
函数
function closest(el, selector) {
const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
while (el) {
if (matchesSelector.call(el, selector)) {
return el;
}
el = el.parentElement;
}
return null;
}
- 在
Modal
中添加wrapProps
属性
wrapProps={{ onTouchStart: this.onWrapTouchStart }}
- 在组件上定义
onWarpTouchStart
函数
onWrapTouchStart = (e) => {
// fix touch to scroll background page on iOS
if (!/iPhone|iPod|iPad/i.test(navigator.userAgent)) {
return;
}
const pNode = closest(e.target, '.am-modal-content');
if (!pNode) {
e.preventDefault();
}
}
搜索到可以解决的方法
- 创建一个
fixModalTouchBGScroll.js
文件
function closest(el, selector) {
const matchesSelector =
el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector
while (el) {
if (matchesSelector.call(el, selector)) {
return el
}
el = el.parentElement
}
return null
}
/**
* 修复antd-mobile Modal组件touch事件穿透
* 需要滚动的地方请加class: 'scroller'
* 参考代码:
* https://mobile.ant.design/components/modal-cn/
* http://www.zhangxinxu.com/study/201612/mobile-scroll-prevent-window-scroll.html
*/
export default function fixModal() {
let data = {
scroller: null,
posY: 0,
scrollY: 0,
maxscroll: 0
}
function isIosModalVisible() {
return (
/iPhone|iPod|iPad/i.test(navigator.userAgent) &&
document.body.style.overflow === 'hidden' &&
document.querySelectorAll('.am-modal').length > 0
)
}
document.body.addEventListener(
'touchstart',
function (e) {
if (!isIosModalVisible()) return
const scroller = closest(e.target, '.scroller')
if (!scroller) return
data.scroller = scroller
// 垂直位置标记
data.posY = e.touches[0].pageY
data.scrollY = scroller.scrollTop
// 是否可以滚动
data.maxscroll = scroller.scrollHeight - scroller.clientHeight
}, {
passive: false
}
)
document.body.addEventListener(
'touchmove',
function (e) {
if (!isIosModalVisible()) return
if (!data.scroller) {
return e.preventDefault()
}
const scrollTop = data.scroller.scrollTop
const distanceY = e.touches[0].pageY - data.posY
// 上下边缘检测
if (distanceY > 0 && scrollTop === 0) {
// 往上滑,并且到头
// 禁止滚动的默认行为
return e.preventDefault()
}
// 下边缘检测
if (distanceY < 0 && scrollTop + 1 >= data.maxscroll) {
// 往下滑,并且到头
// 禁止滚动的默认行为
return e.preventDefault()
}
}, {
passive: false
}
)
document.body.addEventListener(
'touchend',
function (e) {
if (!isIosModalVisible()) return
data.scroller = null
data.maxscroll = 0
}, {
passive: false
}
)
}
- 在需要使用的组件中引入并在
componentWillMount
生命周期函数中调用
import FixModalTouchBGScroll from 'path/fixModalTouchBGScroll';
componentWillMount() {
FixModalTouchBGScroll();
}
- 需要滚动的地方加class ->
scroller