Обрабатывать щелчок за пределами компонента React и как добавить к нему анимацию? - PullRequest
1 голос
/ 11 апреля 2019

Я прочитал много похожих статей, таких как следующие пункты:

  1. Обнаружение щелчка за пределами реагирующего компонента
  2. Нажмите за пределами кликабельногокомпоненты в React
  3. и т. д.

И я прочитал многие из их ответов, но это не помогло мне решить мою проблему.

У меня есть компонент navbar, на котором есть значок баров.всякий раз, когда пользователь щелкает по нему, он должен показывать компонент sidebar, а в случае, если пользователь щелкает вне компонента sidebar, он должен находиться в скрытом состоянии (как в первый раз).

Вот что у меня естьреализовано:

navbar.js

import React, {Component} from 'react';
import {Icon} from 'antd';

import Sidebar from '../sidebar/sidebar.js';
import '../../css/navbar.css';

class Navbar extends Component {
    constructor(props){
        super(props);
        this.state = {
            sidebarVisible: false
        }
        this.sidebarShow = this.sidebarShow.bind(this);
        this.sidebarHide = this.sidebarHide.bind(this);
    }

    sidebarShow(){
        this.setState({
            sidebarVisible: true
        })
        document.addEventListener('click', this.sidebarHide);
    }

    sidebarHide(){
        this.setState({
            sidebarVisible: false
        })

        document.removeEventListener('click', this.sidebarHide)
    }

    render (){
        return (
            <div className="nav-container">

                <div className="bar" onClick={() => this.sidebarShow()} >
                    <Icon type="bars"/>
                </div>

                <div className="nav-logo">
                    خفت کتاب
                </div>

                {this.state.sidebarVisible ? <Sidebar/> : null}

            </div>
        )
    }
}

export default Navbar

sidebar.js

import React, { Component } from 'react'
import {Icon} from 'antd';

import '../../css/sidebar.css'

class Sidebar extends Component {
    render(){
        return (
            <div className="sidebar">
                <div className="sidebar-user">
                    <div className="sidebar-profile">
                        <img src={require('../../images/personal.jpg')}/>
                    </div>
                    <div className="sidebar-welcome">
                        مصطفی قدیمی
                    </div>
                </div>
                <div className="sidebar-active sidebar-elements">
                    <div className="sidebar-icon">
                        <Icon type="home" />
                    </div>
                    <div className="sidebar-title">
                        خانه
                    </div>
                </div>

                <div className="sidebar-elements">
                    <div className="sidebar-icon">
                        <Icon type="book" />
                    </div>
                    <div className="sidebar-title">
                        ثبت کتاب
                    </div>
                </div>

                <div className="sidebar-elements">
                    <div className="sidebar-icon">
                        <Icon type="info-circle" />
                    </div>
                    <div className="sidebar-title">
                        درباره ما
                    </div>
                </div>

                <div className="sidebar-elements">
                    <div className="sidebar-icon">
                        <Icon type="mail" />
                    </div>
                    <div className="sidebar-title">
                        تماس با ما
                    </div>
                </div>

            </div>
        )
    }
}

export default Sidebar;

sidebar.css

.sidebar {
    position: fixed;
    width: 250px;
    height: 100vh;
    background-color: #001529;
    z-index: 1;
    top: 0;
    right: 0;
    color: white;
    animation-name: 'sidebar';
    animation-duration: 1s;
    animation-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
}

.sidebar > div {
    padding: 10px;
}


.sidebar-elements {
    background-color: #334454;
    opacity: 0.4;
    display: grid;
    grid-template-columns: 40px auto;
    margin-bottom: 5px;
}

.sidebar-elements:hover {
    opacity: 1;
    transition-duration: .5s;
}

.sidebar-icon {
    display: flex;
    align-content: center;
}

.sidebar-profile {
    margin: auto;
    background-color: #334454;
    width: 150px;
    height: 150px;
    box-sizing: border-box;
    padding: 0;
    border-radius: 50%;
    position: relative;
    overflow: hidden;
}

.sidebar-profile > img {
    display: block;
    position: absolute;
    top: 50%;
    left: 50%;
    width: 100%;
    height: auto;
    transform: translate(-50%, -50%)
}

.sidebar-welcome {
    margin: auto;
    text-align: center;
    font-size: 14px;
    color: white;
}

.sidebar-active {
    background-color: #1890ff;
    opacity: 1;
}

@keyframes sidebar {
    from {transform: translateX(250px);}
    to {transform: translateX(0);}
}

@-webkit-keyframes sidebar { 
    from {transform: translateX(250px);}
    to {transform: translateX(0);}
}

Основная проблемаэтой реализации всякий раз, когда пользователь нажимает на компонент sidebar, он становится невидимым.Как предотвратить это от сокрытия? Примечание: Есть ли способ добавить анимацию, когда пользователь нажимает за пределы компонента?

Ответы [ 3 ]

1 голос
/ 11 апреля 2019

Если вы хотите добавить анимацию, вы можете создать класс css для компонента боковой панели .is-visible и вместо этого:

{this.state.sidebarVisible ? <Sidebar/> : null}

вы можете сделать это:

<Sidebar isVisible={this.state.sidebarVisible} />

Теперь в зависимости от значения isVisible prop добавьте или удалите класс is-visible из контейнера компонента боковой панели, т. Е. <div className="sidebar">

Youможет сделать это так

.sidebar {
  ...,
  width: 320px;
  transition: transform 0.2s linear;
  transform: translateX(-320px); // assuming the sidebar is on the left side
}

.sidebar.is-visible {
  transform: translateX(0);
}

Надеюсь, это поможет!

0 голосов
/ 24 апреля 2019

Проблема была в том месте, где я добавил EventListener для всего документа!

Я изменил стиль кодирования (как сказал @ AjayGupta ) следующим образом:

Решение первой проблемы: Это было исправлено чтением трюка в этом посте . Чтобы кратко объяснить это, я добавил переменную игнорирования, которая всякий раз, когда пользователь нажимает на компонент боковой панели, возвращает функцию и больше ничего не делает.

Sidebar.js

import React, {Component} from 'react';
import {Icon} from 'antd';

import Sidebar from '../sidebar/sidebar.js';
import '../../css/navbar.css';

class Navbar extends Component {
    constructor(props){
        super(props);
        this.state = {
            sidebarVisible: false
        }
        this.sidebarShow = this.sidebarShow.bind(this);
        this.sidebarHide = this.sidebarHide.bind(this);
    }

    sidebarShow(){

        this.setState({
            sidebarVisible: true
        })
        document.querySelector('.sidebar').className = "sidebar sidebar-in"
        document.querySelector('.sidebar').style.display = "block"
        document.addEventListener('click', this.sidebarHide);

    }

    sidebarHide(e){
        // TODO: implement sidebar in a different way

        this.setState({
            sidebarVisible: false
        })

        var ignore = document.querySelector('.sidebar')
        var target = e.target
        if (target === ignore || ignore.contains(target)) {
            return
        }
        document.querySelector('.sidebar').className = "sidebar sidebar-out"
        setTimeout(
            () => document.querySelector('.sidebar').style.display = 'none'
        , 800)
        document.removeEventListener('click', this.sidebarHide)
    }

    render (){
        return (
            <div className="nav-container">

                <div className="bar" onClick={() => this.sidebarShow()} >
                    <Icon type="bars"/>
                </div>

                <div className="nav-logo">
                    خفت کتاب
                </div>

                <Sidebar/>

            </div>
        )
    }
}

export default Navbar

Решение второй проблемы: я добавил два класса (sidebar-in и sidebar-out и добавил их к классу sidebar в соответствующих ситуациях:

sidebar.css

.sidebar {
    position: fixed;
    width: 250px;
    height: 100vh;
    background-color: #001529;
    z-index: 1;
    top: 0;
    right: 0;
    color: white;
    display: none;
}

.sidebar-in {
    animation-name: 'sidebar-in';
    animation-duration: 1s;
    animation-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
}

.sidebar-out {
    animation-name: 'sidebar-out';
    animation-duration: 1s;
    animation-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
}

@keyframes sidebar-in {
    from {transform: translateX(250px);}
    to {transform: translateX(0);}
}

@keyframes sidebar-out {
    from {transform: translateX(0);}
    to {transform: translateX(250px);}
}
0 голосов
/ 11 апреля 2019
import '../../css/sidebar.css'

class Sidebar extends Component {
  render(){
    return (
        <div className="sidebar" onClick={event => event.stopPropagation()}>
            <div className="sidebar-user">
                <div className="sidebar-profile">
                    <img src={require('../../images/personal.jpg')}/>
                </div>
                <div className="sidebar-welcome">
                    مصطفی قدیمی
                </div>
            </div>
            <div className="sidebar-active sidebar-elements">
                <div className="sidebar-icon">
                    <Icon type="home" />
                </div>
                <div className="sidebar-title">
                    خانه
                </div>
            </div>

            <div className="sidebar-elements">
                <div className="sidebar-icon">
                    <Icon type="book" />
                </div>
                <div className="sidebar-title">
                    ثبت کتاب
                </div>
            </div>

            <div className="sidebar-elements">
                <div className="sidebar-icon">
                    <Icon type="info-circle" />
                </div>
                <div className="sidebar-title">
                    درباره ما
                </div>
            </div>

            <div className="sidebar-elements">
                <div className="sidebar-icon">
                    <Icon type="mail" />
                </div>
                <div className="sidebar-title">
                    تماس با ما
                </div>
            </div>

        </div>
    )
}

}

экспортировать боковую панель по умолчанию;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...