• 自定义组件 鼠标移入显示/隐藏 组件思路


    刚出来时候 做这种类似的效果,都是 通过 css hover 效果,把组件 包在父级中,通过父级的 hover 事件,来控制 里面子级 的显示与隐藏。

    这样使用,一: 如果是列表里面做这个功能,就会出现很多这种组件,明明 一个就可以做这件事,就很浪费性能

         二: 组件嵌套在业务代码里面,不好管理 与复用,维护成本高。

    添加在body 上这种方式没自己写过,后面一直都是 使用 antd  或者其他组件库,现在写了,记录下思路

    这个效果 需要注意 几点

    1. 就是 组件显示的位置。

    2. 显示隐藏之间如果过渡,

    先辨别下 鼠标移入/移出事件

    mouseenter  鼠标移入目标触发

    mouseleave 鼠标移出目标触发

    mouseover 鼠标移入目标触发,其子元素也会触发

    mouseout 鼠标移出目标触发,其子元素也会触发

    所以应该用 mouseenter 和  mouseleave, 来处理事件,

    1. 通过 mouseenter 拿到 event 对象,来获取 元素自身宽高 和 元素距离 文档顶部的距离,和左边的距离, 来定位元素显示的位置。特定的情况还可以判断 距离底部位置,从而适当上移显示组件,或者监听 窗口变化 resize 事件来 实时变化显示组件的位置,不过鼠标移入移出显示应该不用

    // 设置组件显示的位置
        setPosition = () => {
            const { event } = this.props;
            let $dom = event.currentTarget;
            let top = $dom.offsetTop + $dom.clientHeight + 5;
            let left = $dom.offsetLeft;
            this.setState({
                top,
                left
            })
        }

    2. 就是 显示与隐藏了,

      (1)在通过鼠标移入/移出控制,那么这个按钮可能有个 hover 效果,但是 这里不能用 hover ,因为组件是直接添加到body 根部不 鼠标进入到组件,就没效果了,这里应该用事件判断来控制效果。

      (2)在鼠标移入按钮 可以展示组件,那么 离开按钮之后呢,同上,鼠标在从组件回到按钮上 ,组件怎么显示的问题。

    在 鼠标移出按钮的时候 加一个 定时事件,setTimeout  设置时间 0.2s,在日历组件的移入事件中加一个 clearTimeout, 在时间到之前 进入日历组件,那么组件依旧展示,否则,组件关闭,

    在鼠标从组件回到按钮 也是一样,设置一个定时器,在 按钮的移入事件中加一个 判断 是否有定时器,有的话则表示是从组件回来的,可进行清空,如果判断没有,则就重新开始,可直接显示组件,并且要在相对的时机,置空定时器的变量(时长可根据实际情况设置,鼠标移动还是很快的)

    import React from 'react';
    import moment from 'moment';
    import Calendar from "./calendar";
    import './index.less';
    
    type P = {
    
    }
    let timer: any = null;
    class Index extends React.Component<P, any> {
        str = moment().format('YYYY-MM');
        constructor(props: P) {
            super(props);
            this.state = {
                flg: false, // 控制 按钮的 hover 效果
            }
        }
        componentDidMount() {
        }
        // 日历显示
        show = (e: any) => {
            this.setState({
                flg: true
            })
            let data = {
                text: this.str,
                // 这里是 给日历组件传了2个回调事件,移出/移入
                mouseenter: this.calendarMouseEnter,
                mouseleave: this.calendarMouseLeave,
                event: e
            }
            Calendar.open(data);
        }
        // 日历隐藏
        hide = () => {
            timer = setTimeout(() => {
                this.setState({
                    flg: false
                })
                Calendar.remove('');
                timer = null;
            }, 200);
        }
        // 按钮鼠标移入
        mouseenter = (e: any) => {
            e.stopPropagation();
            if (timer) {
                clearTimeout(timer);
                timer = null;
            } else {
                this.show(e);
            }
        }
        // 按钮鼠标移出
        mouseleave = (e: any) => {
            e.stopPropagation();
            const { flg } = this.state
            if (flg) {
                this.hide();
            }
        }
        // 日历鼠标移入
        calendarMouseEnter = (e: any) => {
            e.stopPropagation();
            clearTimeout(timer);
            timer = null;
        }
        // 日历鼠标移出
        calendarMouseLeave = (e: any) => {
            e.stopPropagation();
            this.hide();
        }
        render() {
            const { flg } = this.state;
            return (
                <div className="oper-calendar">
                    <span className={flg ? "title hover" : "title"} onMouseEnter={this.mouseenter} onMouseLeave={this.mouseleave}>{this.str}</span>
                </div>
            )
        }
    }
    
    export default Index;
  • 相关阅读:
    今年暑假不AC
    亲和数
    改革春风吹满地
    hdu人见人爱A^B
    男人必看的10部电影
    富人和穷人之间的经典差异
    今日十句英文
    看透一个人起码要看的。
    人生经典20句
    解决ubuntu中mysql中文乱码问题
  • 原文地址:https://www.cnblogs.com/bruce-gou/p/11236744.html
Copyright © 2020-2023  润新知