获取第一个未读元素的offsetTop

时间:2019-04-23 16:34:26

标签: reactjs

我需要将聊天滚动到第一条未读消息。 我有父组件MessagesList,其中包含map函数内的childComponent。 我需要深入研究并从那里获得具有属性的第一个未读元素(item.status ===“ new”) 在componentDidMount内部的MessagesList中,我需要使用

 componentDidMount() {
        this.scrollToFirstUnreadMessage()
 }
 scrollToFirstUnreadMessage = () => {
        let firstUnreadElement = document.querySelector('.MessagesItem__root__support_new, .MessagesItem__root__writer_new');
        let valueToScroll = (firstUnreadElement && firstUnreadElement.offsetTop) - 360;
        let listContainer = this.listRef.current;
        console.log(listContainer);
        if(valueToScroll > 0) {
            listContainer.scrollTop = valueToScroll;
        } else {
            listContainer.scrollTop = listContainer.scrollHeight;
        }
 }

此JS行的主要问题:

 let firstUnreadElement = document.querySelector('.MessagesItem__root__support_new, .MessagesItem__root__writer_new');

如何通过反应仪器获得该元素。 并在此处发布两个组件:

import React, {Component} from "react";
import { debounce } from "lodash";

import MessagesItem from "../MessagesItem";
import css from "./MessagesList.styl";

export default class MessagesList extends Component {

    static propTypes = {

    };

    constructor (props) {
        super(props);
        this.listRef = React.createRef();
        this.state = {
            listHeight: 0
        }
        this.state.itemIndex = 0;
    }

    componentDidMount() {
        this.scrollToFirstUnreadMessage()
    }

    scrollToFirstUnreadMessage = () => {
        let firstUnreadElement = document.querySelector('.MessagesItem__root__support_new, .MessagesItem__root__writer_new');
        let valueToScroll = (firstUnreadElement && firstUnreadElement.offsetTop) - 360;
        let listContainer = this.listRef.current;
        console.log(listContainer);
        if(valueToScroll > 0) {
            listContainer.scrollTop = valueToScroll;
        } else {
            listContainer.scrollTop = listContainer.scrollHeight;
        }
    }

    listHasScrolledToBottom = () => {
        let listContainer = this.listRef.current;
        if (listContainer.scrollHeight === listContainer.scrollTop + listContainer.offsetHeight) return true;
    }

    hasVerticalScrollbar = () => {
        let listContainer = this.listRef.current;
        if (listContainer.scrollHeight > listContainer.clientHeight) return true;
    }

    /**
     * Sort messages
     * @param messages
     * @returns {*}
     */
    sortMessages = (list) => {
        list.sort(function (a, b) {
            return new Date( b.sended ).getTime() - new Date( a.sended ).getTime();
        });
        return list;
    }

    onMouseEnter = (e) => {
        if (!this.hasVerticalScrollbar()) {
            this.props.markAllOnScrollToBottom(true);
        }
    }

    onScroll = (e) => {
        if (this.listRef.current.scrollTop === 0 && this.props.supportNextPage) {
            let oldListHeight = this.listRef.current.scrollHeight;
            setTimeout( function () {
                let newListHeight = this.listRef.current.scrollHeight;
                this.listRef.current.scrollTop = newListHeight - oldListHeight;
            }.bind( this ), 100 );
            this.props.getMessages(this.props.currentProcess);
        }

        if(this.listHasScrolledToBottom()) {
            this.props.markAllOnScrollToBottom(true, this.props.currentProcess);
        }
    }

    /**
     * Added today and yesterday separator items
     * @param messages
     * @returns {Array}
     */
    formatMessages = (list) => {
        var today = new Date();
        today.setHours(0);
        today.setMinutes(0);
        today.setSeconds(0);

        var yesterday = new Date();
        yesterday.setHours(0);
        yesterday.setMinutes(0);
        yesterday.setSeconds(0);
        yesterday.setDate(today.getDate() - 1);

        var laterList = [];
        var yesterdayList = [];
        var todayList = [];
        for (var i = 0; i < list.length; i++) {
            if (new Date( list[i].sended ).getTime() < (yesterday.getTime() / 1000)) {
                laterList.push(list[i]);
                // console.log("later");
            } else if (new Date( list[i].sended ).getTime() < (today.getTime() / 1000)) {
                yesterdayList.push(list[i]);
                // console.log("yesterday");
            } else {
                todayList.push(list[i]);
                // console.log("today");
            }
        }

        var result = [];

        if (laterList.length) {
            result = laterList;
        }

        if (yesterdayList.length) {
            if (result.length) {
                result.push({yesterday: true, id: 'yesterday'});
            }
            result = result.concat(yesterdayList);
        }

        if (todayList.length) {
            if (result.length) {
                result.push({today: true, id: 'today'});
            }
            result = result.concat(todayList);
        }

        return result;
    }

    /**
     * Prepare messages (sort and format)
     * @param messages
     * @returns {Array.<T>}
     */
    prepareMessages = (list) => {
        list = this.sortMessages(list);
        list = list.reverse();

        return this.formatMessages(list);
    }

    render () {
        const { list } = this.props;
        return (
            <ul
            className={css.root}
            ref={this.listRef}
            onScroll={ debounce(this.onScroll,100) }
            onMouseEnter={ this.onMouseEnter }
            >

                {
                    list &&
                    this.prepareMessages(list).map((item, index) => {
                        if (item.today) {
                            return (
                                <div key="today" className="text-center message-day">
                                    <span className="message-day-text">{this.props.t.today}</span>
                                </div>
                            );
                        }
                        if (item.yesterday) {
                            return (
                                <div key="yesterday" className="text-center message-day">
                                    <span className="message-day-text">{this.props.t.yesterday}</span>
                                </div>
                            );
                        }
                        return (
                            <MessagesItem
                                key={index}
                                item={item}
                            />
                        );
                    })
                }
            </ul>
        )
    }

}

import React, {Component} from "react";
import PropTypes from 'prop-types';
import classNames from 'classnames';
import css from "./MessagesItem.styl"

export default class MessagesItem extends Component {
    static propTypes = {
        item: PropTypes.shape({
            msg: PropTypes.string,
            message_type: PropTypes.string,
            id: PropTypes.number,
            status: PropTypes.string,
            sender_name: PropTypes.string,
            sended: PropTypes.string
        }).isRequired
    };

    constructor(props) {
        super(props);

        this.itemRef = React.createRef();
    }

    render () {
        const { item } = this.props;
        let formattedTimeOptions = { year: 'numeric', month: 'long', day: 'numeric'};
        let formattedTimeVal = new Date( item.sended ).toLocaleDateString(this.props.locale, formattedTimeOptions);
        return (

            <li
            ref= { this.itemRef }
            key= { item.id }
            // isOnViewport = {this.isOnViewport}
            className={classNames(css.root, {
                [css.root__support_new]: item.status  === "new" && item.message_type === "support_customer",
                [css.root__writer_new]: item.status  === "new" && item.message_type === "writer_customer",
                [css.root__read]: item.status === "read"
            })}
            >
                <div className={classNames(css.root__content, {
                    [css.root__content__left] : item.message_type === "support_customer",
                    [css.root__content__left_writer] : item.message_type === "writer_customer",
                    [css.root__content__right] : item.message_type === "customer_support" || item.message_type === "customer_writer",
                })}>
                    <div className={css.root__author}>
                        <div className={css.root__name}>{item.sender_name}</div>
                        <div className={css.root__date}>{formattedTimeVal}</div>
                    </div>
                    <div className={css.root__message}>{item.msg}</div>
                </div>
            </li>
        )
    }
}

请不要对初中坚强:)

0 个答案:

没有答案