下拉加载弹窗

kingcwt2019-12-05前端react

项目笔记

监听外层盒子scroll


// pagination.page 后端传来的页数

/**
   * 下拉modal 加载更多
   */
  useEffect(() => {
    if (is.empty(pagination)) return;
    let timeCount;
    function callback() {
      /**
       * getBoundingClientRect()
       * top 指当前加载元素距离屏幕顶部的距离
       */
      const { top } = wrapperRef.current.getBoundingClientRect();
      /**
       * window.screen.height 获取当前屏幕的高度
       */
      const windowViewHeight = window.screen.height;
      // 屏幕的高度 - 加载盒子的高度
      const viewBoxHeight = windowViewHeight - 25;
      /**
       * 当top的值小于屏幕的高度的时候 就加载更多
       */
      if (top && top < viewBoxHeight) {
        loadMoreDataFn();
      }
    }
    /**
     * 监听外层的盒子 滚动事件
     */
    listContainerRef.current.addEventListener('scroll', () => {
      // 加载到最后没有数据的时候 就让盒子消失 所以就会变为null 直接返回
      if (wrapperRef.current == null) return;
      if (is.empty(pagination)) return;
      if (!pagination.has_more) return;
      if (timeCount) clearTimeout(timeCount);
      timeCount = setTimeout(callback, 50);
    }, false);
  }, [pagination.page]);

请求后端数据

// 后端page页数 发生变化再加载请求后端接口
  let flag = pagination.page;
  // flag 保证每次都加载请求一次
  const loadMoreDataFn = () => {
    if (pagination.page === flag) {
      flag += 1;
      const { _id } = account.account;
      const param = {
        manage_type: [20, 30],
        account_id: _id,
      };
      dispatch({ type: 'mAccountbillIncome/fetchLoadingRoomList', payload: { ...param, _meta: { page: flag, limit: 10 } } });
    }
  };

modal弹窗组件

<ComponentFooterModal
        wrapperRef={wrapperRef}
        listContainerRef={listContainerRef}
        pagination={pagination}
        dropDownElement={dropDownElement}
        isSelectItem={isSelectItem}
        onSelectListItem={onSelectListItem}
        dropDown={dropDown}
        onSelectDefine={onSelectDefine}
        onSelectCancel={onSelectCancel}
        dataLists={roomListsData}
      />

ComponentFooterModal

/**
 * 房间下拉列表 modal
 */
import React from 'react';
import PropTypes from 'prop-types';
import { List } from 'antd-mobile';
import styles from '../style.module.less';
import selectImg from '../../../static/select.png';
import roomIco from '../../../static/roomico.jpg';
import ComponentLoading from './loading';

const { Item } = List;
const { Brief } = Item;

const ComponentFooterModal = ({
  wrapperRef, listContainerRef, dropDown, onSelectDefine, onSelectCancel, dataLists, isSelectItem, onSelectListItem, pagination,
}) => {
  // 弹窗头部
  const renderHeader = () => (
    <header className={styles['page-billincome-footer-bottom-headerbox']}>
      <p className={styles['page-billincome-footer-bottom-headerbox-leftp']}> <span onClick={onSelectCancel}>取消</span></p>
      <h4>选择房源</h4>
      <p className={styles['page-billincome-footer-bottom-headerbox-rightp']}> <span onClick={onSelectDefine}>确定</span></p>
    </header>
  );

  // 弹窗底部
  const renderFooter = () => (
    <div ref={listContainerRef} className={styles['page-billincome-components-footermodal-list']}>
      {
            dataLists.map(i => (
              // eslint-disable-next-line no-underscore-dangle
              <div className={styles['page-billincome-components-footermodal-section-box']} onClick={() => onSelectListItem(i)} key={i._id}>
                <Item
                  className={styles['page-billincome-component-header-list-item']}
                  thumb={i.house_cover_asset_info ? i.house_cover_asset_info.url : roomIco}
                  multipleLine
                  onClick={() => {}}
                >
                  <span className={styles['page-billincome-component-footermodal-title']}>{i.name}</span>
                  <Brief> <span className={styles['page-billincome-component-footermodal-describe']}>{i.product_info ? i.product_info.name : null}</span></Brief>
                  {
                // eslint-disable-next-line no-underscore-dangle
                isSelectItem._id === i._id
                  ? <img alt="" className={styles['page-billincome-components-footermodal-img']} src={selectImg} />
                  : null
                }
                </Item>
              </div>
            ))
        }
      {!pagination.has_more ? null : <ComponentLoading wrapperRef={wrapperRef} />}
    </div>
  );

  return (
    <footer className={styles['page-billincome-footer']} style={dropDown ? { transform: 'translateY(0)', transitionDuration: '.1s' } : { transform: 'translateY(100vh)', transitionDuration: '.1s' }}>
      <div className={styles['page-billincome-footer-top']} onClick={onSelectCancel} />
      <div className={styles['page-billincome-footer-bottom']}>
        {/* 渲染弹窗头部 */}
        {renderHeader()}
        {/* 渲染弹窗底部 */}
        {renderFooter()}
      </div>
    </footer>
  );
};
/**
 * props: {dropDown} type:bool true:显示弹窗 false:关闭弹窗
 * props: {isSelectItem} type:object 列表点击切换选中的某一项 我们拿这一项的value进行数据中的value匹配 以达到选中效果
 * props: {dataLists} type:array 列表循环的数据
 * props: {onSelectDefine}    type:func    点击确定提交触发的事件   都关闭弹窗
 * props: {onSelectCancel}   type:func    点击取消提交触发的事件   都关闭弹窗
 * props: {onSelectListItem} type:func    选中列表下某一项触发的事件(列表点击切换选中事件)
 * props: {dropDownElement}  type:object  房间列表下拉元素 ref
 */
ComponentFooterModal.propTypes = {
  dropDown: PropTypes.bool,
  dataLists: PropTypes.array,
  isSelectItem: PropTypes.object,
  onSelectDefine: PropTypes.func.isRequired,
  onSelectCancel: PropTypes.func.isRequired,
  onSelectListItem: PropTypes.func.isRequired,
  pagination: PropTypes.object,
  wrapperRef: PropTypes.object.isRequired,
  listContainerRef: PropTypes.object.isRequired,
};
ComponentFooterModal.defaultProps = {
  dropDown: false,
  isSelectItem: {},
  dataLists: [],
  pagination: {},

};


export default ComponentFooterModal;


ComponentLoading

import React from 'react';
import styles from '../style.module.less';

const componentLoading = ({ wrapperRef }) => (
  <div className={styles.loading} ref={wrapperRef}>
    <span />
    <span />
    <span />
    <span />
    <span />
  </div>
);
export default componentLoading;

style.module.less

.page-billincome-main-icon-box{
    display: flex;
    justify-content: center;
    align-items: center;
    padding-bottom: 10px;
    background-color: #fff;
    padding-bottom: .15rem;
    margin-top:.1rem;
    span{
        background: #FFF6E8;
        color: #F38C27;
        width: 120px;
        display: flex;
        justify-content: center;
        align-items: center;
        height: .4rem;
        border-radius: 0 0 .42rem .42rem;
        padding: 3px 20px;
    }
}
// .page-billincome-detail-header-box{
//     margin-top: 5px;
// }

.page-billincome-detail-header-box-span{
    display: flex;
    justify-content: center;
    align-items: center;
}
.page-billincome-main-icon-box-list-left-green-span{
    color: #18b350;
}
.page-billincome-main-icon-box-list-left-grey-span{
    color: #b1b1b1;
    font-size: 12px;
    margin-left:6px;
}
.page-billincome-detail-main-icon{
    display: flex;
    align-items: center;
    margin-top: 10px;
    background: rgba(244, 249, 255, 1);
    padding: 10px 5px;
    padding-left: .15rem;
    color: rgba(90, 154, 229, 1);
    height: .44rem;
    box-sizing: border-box;
    font-size: .16rem;
    
    // .page-billincome-detail-main-icon-leftBox{ 
    //     background: #8bce7b;
    //     color: #fff;
    //     width: 40%;
    //     display: flex;
    //     justify-content: center;
    //     align-items: center;
    //     height: 35px;
    // }
    // .page-billincome-detail-main-icon-rightBox{
    //     background: #b2dda9;
    //     color: #333;
    //     width: 60%;
    //     display: flex;
    //     justify-content: start;
    //     align-items: center;
    //     height: 35px;
    //     padding-left: 10px;
    //     box-sizing: border-box;
    // }
}

.page-billincome-detail-main-icon-box{
    background: #fff;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    position: relative;
    // padding-bottom: 15px;
    padding-top: .28rem;
    .page-billincome-main-icon-box-main{
        display: flex;
        flex-direction: column;
        justify-content: center;
        color: #999;
        width: 100%;
        align-items: self-end;
        padding-left: 16px;
        box-sizing: border-box;
        border-top: 1px solid #eee;
        
        .page-billincome-main-icon-box-main-titleMain{
            color: #999;
            margin-bottom: 0px;
        }
    }
}
.page-billincome-detail-bill-amount-one{
    font-size: .3rem;
    margin: .1rem 0 .2rem 0;
    // color:#000;
}
.page-billincome-detail-bill-amount-two{
    font-size: .3rem;
    margin: .1rem 0 .2rem 0;
    color:#ED0E0E;
}

.page-billincome-main-icon-box-footerBox-redSpan{
    color: #e83333;
}
.page-billincome-main-icon-box-footerBox-blueSpan{
    color: #108ee9;
}

.page-billIncome-main-iconBox-mylist{
    background-color: #fff;
    padding: 0 14px;
    .am-list-header{
      background: #f5f6f7;
      padding: 8px 9px;
    }
}
.page-billIncome-main-iconBox-mylist>div:nth-child(1){
    background: #f5f6f7;
    padding: 8px 9px;
}
.page-billincome-main-icon-box-main-p{
    margin: 5px 0;
}
.page-billIncome-main-iconBox-list-span{
    color: #333;
}
.page-billincome-main-icon-box-position-title{
    width: 73px;
    height: 32px;
    background: rgba(255, 235, 235, 1);
    color: rgba(206, 137, 115, 1);
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 12px;
    border-radius: 100px 0px 0px 100px;
    position: absolute;
    right: 0px;
    top: 2px;
}
.page-billincome-detail-button{
    width: 3.82rem;
    height: 0.47rem;
    border-radius: 0.04rem;
    display: flex;
    justify-content: center;
    align-items: center;
    margin: 0.84rem auto .34rem auto;
}

.page-billincome-detail-modal-content{
    margin-top: 5px;
}
.page-billincome-footer{
    width: 100%;
    height: 100%;
    // background: #fff;
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    z-index: 99999;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    .page-billincome-footer-top{
        // background: #000;
        width: 100%;
        height: 100%;
        opacity: 0.3;
        filter: alpha(opacity=30);
        -moz-opacity:0.3;
        -khtml-opacity:0.5;
        z-index: 999999;
        background-color: #000;
    }

    .page-billincome-footer-bottom{
        width: 100%;
        background: #eee;
        max-height: 6.1rem;
        background: #acacaf;
        .page-billincome-footer-bottom-headerbox{
            background: rgba(248, 248, 248, 1);
            height: .49rem;
            border-radius: .12rem .12rem 0 0;
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 0 20px;
            .page-billincome-footer-bottom-headerbox-leftp{
                color:rgb(111 101 101);
               span{
                padding: .12rem;
               }
            }
            .page-billincome-footer-bottom-headerbox-rightp{
                color:rgba(245, 147, 0, 1);
                span{
                    padding: .12rem;
                }
            }
    }
}}


.page-billIncome-detail-hedaer-imgBox{
    display:flex;
    .page-billIncome-detail-hedaer-imgBox-img{
        margin-right: 18px;
        width: 40px;
        height: 40px;
    }
}
.page-billincome-detail-main-icon-green{
    display: flex;
    align-items: center;
    margin-top: 10px;
    background: rgba(245, 255, 249, 1);
    padding: 10px 5px;
    padding-left: .15rem;
    color: rgba(74, 193, 120, 1);
    height: .44rem;
    box-sizing: border-box;
    font-size: .16rem;
}
.page-billincome-detail-main-icon-yellow{
    display: flex;
    align-items: center;
    margin-top: 10px;
    background: rgba(255, 250, 243, 1);
    padding: 10px 5px;
    padding-left: .15rem;
    color: rgba(240, 154, 25, 1);
    height: .44rem;
    box-sizing: border-box;
    font-size: .16rem;
}
.page-billincome-detail-main-icon-grey{
    display: flex;
    align-items: center;
    margin-top: 10px;
    background: rgba(255, 255, 255, 1);
    padding: 10px 5px;
    color: rgba(175, 175, 199, 1);
    height: .44rem;
    box-sizing: border-box;
    border-bottom: 1px solid #dfdfff;
    height: .44rem;
    padding-left: .15rem;
    font-size: .16rem;
}
.page-billincome-detail-main-icon-error{
    display: flex;
    align-items: center;
    margin-top: 10px;
    background: rgba(255, 255, 255, 1);
    padding: 10px 5px;
    padding-left: .15rem;
    color:red;
    height: .44rem;
    box-sizing: border-box;
    font-size: .16rem;
}
.page-billincome-main-icon-box-switch-ico{
    width:16px;
    margin-left:5px;
}

.page-billincome-components-footermodal-section-box{
    min-height: 60px;
    height: .92rem;
    border-bottom: 1px solid #eee;
    z-index: 999999999;
    .page-billincome-components-footermodal-img{
        position: absolute;
        width: .33rem;
        height: .3rem;
        display: block;
        top: 50%;
        right: 17px;
        margin-top: -15px;
    }
}
// 房间头部占位符
.page-billincome-header-roomlist-placeholder{
    height: 50px;
    width: 100%;
    background: #fff;
}
.page-billincome-list-child-item-amount{
    color:#000;
}


.page-billincome-header-list-item{
    padding: .16rem;
    img{
        width: .6rem;
        height: auto;
    }
}
.page-billincome-component-header-list-item{
    height: 100%;
    img{
        width: .6rem;
        height: auto;
    }
}

.page-billincome-detail-in-out-date{
    font-size: .14rem;
}

.page-billincome-render-select-tab-bill{
    display: flex;
    justify-content: center;
    align-items: center;
    height: calc(100vh - 2rem);
    img{
        width: 1.6rem;
        height: auto;
    }
}

.page-billincome-components-footermodal-list{
    height: 400px;
    overflow-y: auto;
    background-color: #fff;
    z-index: 9999;
}
.page-billincome-components-footermodal-placeholder{
    background: #fff;
    border: 1px solid red;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 20px;
    height: .5rem;
    margin: .1rem;

}




.loading{
    width: 100%;
    height: .2rem;
    margin: 10px 0;
    text-align: center;
    display: flex;
    justify-content: center;
    align-items: center;
}
.loading span{
    display: inline-block;
    width: 15px;
    height: 100%;
    margin-right: 5px;
    background: lightgreen;
    -webkit-animation: load 1.04s ease infinite;
}
.loading span:last-child{
    margin-right: 0px; 
}
@-webkit-keyframes load{
    0%{
        opacity: 1;
    }
    100%{
        opacity: 0;
    }
}
.loading span:nth-child(1){
    -webkit-animation-delay:0.13s;
}
.loading span:nth-child(2){
    -webkit-animation-delay:0.26s;
}
.loading span:nth-child(3){
    -webkit-animation-delay:0.39s;
}
.loading span:nth-child(4){
    -webkit-animation-delay:0.52s;
}
.loading span:nth-child(5){
    -webkit-animation-delay:0.65s;
}

.page-billincome-component-footermodal-title,.page-billincome-component-footermodal-describe{
    width: 85%;
    display: block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}


Last Updated 10/16/2023, 7:06:22 AM
What do you think?
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
Comments
  • Latest
  • Oldest
  • Hottest
Powered by Waline v2.15.8