react使用hook实现一个ActionSheet(下拉弹窗选择)

react使用hook实现一个ActionSheet(下拉弹窗选择)

ActionSheet

import propTypes from "prop-types";
import React, { Fragment } from 'react';
import styleId, { keyframes } from "styled-components";
const slideIn = keyframes`
  from {
    transform: translateY(100%);
  }
  to {
    transform: translateY(0);
  }
`;

const slideOut = keyframes`
  from {
    transform: translateY(0);
  }
  to {
    transform: translateY(100%);
  }
`;
const ActionSheet = (props)=> {
  const { showSheet,options,onSelect,closeShow,closeOnMaskClick } = props
  const itemChange = (item) => {
    onSelect(item)
  }
  const clickMock = () => {
    if ( closeOnMaskClick ) {
      closeShow()
    }
  }
    return (
      <Fragment>
        {
        showSheet ?
        <ActionSheetWrpa onClick={clickMock}>
            <div className='actionSheet-content'>
              {
                options && options.length ? options.map(item=>{
                  return (
                    <div className='select-item' key={item.value} onClick={()=>{itemChange(item)}}>{item.lable}</div>
                  )
                }) : '暂无数据'
              }
            </div>
        </ActionSheetWrpa>
        : ''
        }
      </Fragment>
    )
}
// props 与 默认值
ActionSheet.propTypes = {
  showSheet: propTypes.bool.isRequired, // 是否展示
  options: propTypes.array.isRequired, // options数据
  onSelect: propTypes.func.isRequired, // 下拉change事件
  closeShow: propTypes.func, // 关闭下拉
  closeOnMaskClick: propTypes.bool, // 点击遮罩层关闭下拉
};
ActionSheet.defaultProps = {
  showSheet: false,
  options: [],
  closeOnMaskClick: true
};
const ActionSheetWrpa = styleId.div`
  position: fixed;
  width: 100vw;
  height: 100vh;
  left: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.55);

  .actionSheet-content {
    position: absolute;
    bottom: 0;
    min-height: 104px;
    width: 100%;
    background: #ddd;
    border-radius: 8px 8px 0 0;
    animation: ${({ showSheet }) => (showSheet ? slideOut  : slideIn)} 0.3s ease-in-out;
    animation-fill-mode: forwards;
    .select-item {
      height: 50px;
      line-height: 50px;
      font-size: 16px;
      margin-bottom: 2px;
      background: #fff;
    }
    .select-item:nth-child(1) {
      border-radius: 8px 8px 0 0;
    }
  }
`
export default ActionSheet

使用组件

import React, { useState } from 'react';
import ActionSheet from "./ActionSheet";
export default function App(props) {
  const [showSheet, setShowSheet] = useState(false);
  const options = [
    {lable: '测试1', value: 1},
    {lable: '测试2', value: 2}
  ]
  const handleSelect = (option) => {
    console.log('handleSelect', option); // 拿到数据
    setShowSheet(false)
  };
  const setshowChange = () => {
    setShowSheet(true)
  }
  const closeShow = () => {
    setShowSheet(false)
  }
    return (
        <div className='content'>
          app {showSheet ? 1 : 0}
          <button onClick={setshowChange}>显示</button>
          <ActionSheet
            options={options}
            showSheet={showSheet}
            onSelect={handleSelect}
            closeShow={closeShow}
            closeOnMaskClick={true}
          />
        </div>
    )
}

效果 (有个问题,就是关闭的时候没有动画,有没有大佬帮忙优化下)

  • 有个问题,就是关闭的时候没有动画,有没有大佬帮忙优化下
    在这里插入图片描述
  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值