自定義組件 鼠標移入顯示/隱藏 組件思路

剛出來時候 作這種相似的效果,都是 經過 css hover 效果,把組件 包在父級中,經過父級的 hover 事件,來控制 裏面子級 的顯示與隱藏。css

這樣使用,一: 若是是列表裏面作這個功能,就會出現不少這種組件,明明 一個就能夠作這件事,就很浪費性能react

     二: 組件嵌套在業務代碼裏面,很差管理 與複用,維護成本高。antd

 

添加在body 上這種方式沒本身寫過,後面一直都是 使用 antd  或者其餘組件庫,如今寫了,記錄下思路less

這個效果 須要注意 幾點dom

1. 就是 組件顯示的位置。ide

2. 顯示隱藏之間若是過渡,性能

 

 

先辨別下 鼠標移入/移出事件this

mouseenter  鼠標移入目標觸發spa

mouseleave 鼠標移出目標觸發code

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;
相關文章
相關標籤/搜索