效果图:
安装库
用到了antd design和github上的一个库:react-chat-element
(1)antd design:
安装:yarn add antd
修改 src/App.css,在文件顶部引入 antd/dist/antd.css
@import '~antd/dist/antd.css';
即可使用antd的组件
(2)react-chat-element:
github网址为:Detaysoft/react-chat-elements
安装:npm install react-chat-elements --save
即可
代码和基本说明
import React, {
createRef} from "react";
import {
ChatList, MessageList} from 'react-chat-elements'
import 'react-chat-elements/dist/main.css';
import {
Button, Row, Col, Divider, Input} from "antd";
const {
TextArea} = Input;
class ChatWidget extends React.Component {
constructor(props) {
super(props);
this.state = {
user: null,
msgDataList: [],
sendMsg: "",
}
this.clickButton = this.clickButton.bind(this);
this.messagesEnd = createRef();
}
componentDidMount() {
let list = [];
for (let i = 0; i < 10; ++i)
list.push({
position: 'left',
type: 'text',
text: 'hello' + i,
date: new Date(),
});
this.setState({
msgDataList: list});
this.setState({
user: this.props.user});
}
componentWillReceiveProps(nextProps, nextContext) {
this.setState({
user: nextProps.user});
}
clickButton() {
let list = this.state.msgDataList;
list.push({
position: 'right',
type: 'text',
text: this.state.sendMsg,
date: new Date(),
})
this.setState({
msgDataList: list});
this.setState({
sendMsg: ""});
}
componentDidUpdate(prevProps, prevState, snapshot) {
this.messagesEnd.scrollTop = this.messagesEnd.scrollHeight;
}
render() {
return (
<Col style={
{
width: 700,
height: 600,
display: 'inline-block',
borderRight: "3px solid",
borderTop: "3px solid",
borderBottom: "3px solid",
}}>
<Row>
<Col style={
{
width: 700,
height: 40,
textAlign: "center",
verticalAlign: "middle",
fontSize: 20
}}>
{
this.state.user == null ? "" : this.state.user.title}
</Col>
</Row>
<Row>
<div style={
{
width: 700,
height: 420,
textAlign: "center",
verticalAlign: "middle",
fontSize: 20,
overflow: "auto",
backgroundColor: "\t#C0C0C0"
}}
ref={
(el) => {
this.messagesEnd = el;
}}
>
<MessageList
className='message-list'
dataSource={
this.state.msgDataList}
/>
</div>
</Row>
<Row>
<Col style={
{
width: 700,
textAlign: "center",
verticalAlign: "middle",
fontSize: 20
}}>
<TextArea rows={
4} onChange={
e => {
this.setState({
sendMsg: e.target.value});
}}
ref={
el => (this.inputRef = el)}
value={
this.state.sendMsg}/>
<Button type="primary" onClick={
this.clickButton}>发送</Button>
</Col>
</Row>
</Col>
);
}
}
class PrivateChatView extends React.Component {
constructor(props) {
super(props);
this.state = {
userList: [],
clickUser: null,
}
}
componentDidMount() {
let list = [];
for (let i = 0; i < 14; ++i)
list.push({
avatar: 'https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png',
alt: 'Reactjs',
title: '用户' + i,
subtitle: 'What are you doing?',
date: new Date(),
unread: Math.floor(Math.random() * 10),
});
this.setState({
userList: list});
this.setState({
clickUser: list[0]});
}
render() {
return (
<div>
<Divider orientation="left" style={
{
color: '#333', fontWeight: 'normal'}}>
私信列表
</Divider>
<Row>
<Col style={
{
width: 400,
height: 600,
display: 'inline-block',
border: "3px solid",
overflow:"auto"
}}>
<ChatList
className='chat-list'
onClick={
e => this.setState({
clickUser: e})}
dataSource={
this.state.userList}/>
</Col>
{
this.state.userList.length == 0 ? <div>无私信</div> : <ChatWidget user={
this.state.clickUser}/>}
</Row>
</div>
);
}
}
export default PrivateChatView;
ChatWidget是右边的对话窗口,PrivateChatView是整个聊天组件(包括了聊天列表和ChatWidget)。
PrivateChatView中的userList表示聊天列表的数组。如果想要改变外表(比如未读什么的),详细可以见react-chat-element中对于chatList的描述。PrivateChatView会传一个user参数给ChatWidget,表示是哪一个用户被点击。
ChatWidget接受PrivateChatView传过来的user参数。msgDataList表示聊天记录数组,通过设置数组元素的position是‘right’还是‘left’来决定是消息气泡显示在左边还是右边。
一些问题:
我设置的PrivateChatView里面的聊天列表和ChatWidget用的是display:inline-block,如果将浏览器缩小显示,聊天列表和ChatWidget就会变成上下显示。