美文网首页
React 初探(十四)

React 初探(十四)

作者: bowen_wu | 来源:发表于2019-02-18 14:04 被阅读17次

    概述

    接下来我们将要完成 Home 页面。Home 页面主要有两个点

    1. 使用 react-sticky
    2. ant-design-mobileModal 组件的背景滚动问题

    Home 页面 UI

    Home UI

    Home 页面功能

    1. 点击头像去往个人中心页面
    2. 页面可以滚动,滚动的时候 searchBar 会 sticky 顶部
    3. 可以通过事件 title 进行搜索
    4. 点击右下方的 + 可以去往创建 TODO 页面

    react-sticky

    Home 页面主要使用了 ant-design-mobileListView 组件,其中借助 react-sticky 将搜索栏在滚动的过程中 sticky 在顶部。这里有官方例子和一些使用方法

    ant-design-mobileModal 组件的背景滚动问题

    这个主要是一个在 IOS 下的问题,当页面可以滚动时,有 Modal 显示的时候,此时滚动页面,Modal 后的页面会跟着滚动。ant-design-mobile 有在文档中说明解决方法,但是我在实践的过程中发现并不能解决。所以又搜索了一下,找到了一个可以解决的方法。

    ant-design-mobile 解决方法

    1. 定义一个 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;
    }
    
    1. Modal 中添加 wrapProps 属性
     wrapProps={{ onTouchStart: this.onWrapTouchStart }}
    
    1. 在组件上定义 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();
        }
      }
    

    搜索到可以解决的方法

    1. 创建一个 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
            }
        )
    }
    
    1. 在需要使用的组件中引入并在 componentWillMount 生命周期函数中调用
    import FixModalTouchBGScroll from 'path/fixModalTouchBGScroll';
    
    componentWillMount() {
        FixModalTouchBGScroll();
    }
    
    1. 需要滚动的地方加class -> scroller

    相关文章

      网友评论

          本文标题:React 初探(十四)

          本文链接:https://www.haomeiwen.com/subject/qzskeqtx.html