功能展示 :
1.用户可输入用户名
2.输入评论内容
3.点击发布
4.用户名和用户评论会被显示在列表里,第一个评论在最上面
5.且显示本条评论离现在过去了多长时间
6.鼠标放在事件上方可显示删除键,点击删除,删除当前
总体结构:
1.components下创建comment文件夹
2.先创建用户输入组件:CommentInput
3.再创建单条用户评论视图:Comment
4.接着创建CommentList组件,将用户评论遍历渲染成评论列表
5.创建CommentApp组件,将CommentInput评论组件和CommentList列表组件渲染到一起
6.再index.js中引入展示
用户输入组件:CommentInput 所有内容
1.创建用户名输入视图模板,
用ref获取input此DOM节点的值,
import {Component} from "react";
import React from "react";
class CommentInput extends Component{
constructor(){
super();
this.state={
//用户名
username:'',
//评论内容
content:''
}
}
//监听用户输入用户名事件
handleUsernameChange=(event)=>{
this.setState({
username:event.target.value
})
};
//监听用户输入评论事件
handleContentChange=(event)=>{
this.setState({
content:event.target.value
})
};
//点击发布事件
handleSubmit=()=>{
if(this.props.submit){
this.props.submit({
username:this.state.username,
content:this.state.content,
createTime:+new Date()
})
}
//点击发布后将state中的评论区域重新至为空
this.setState({
content:''
})
};
//用户名框失去焦点
handleUsernameHold=(event)=>{
//将用户名数据存储到本地
localStorage.setItem('username',event.target.value)
};
//将要装载,在render之前调用;
componentWillMount(){
//改变数据重新渲染前get获取用户名
const username=localStorage.getItem('username');
if(username){
this.setState({username})
}
}
//(装载完成),在render之后调用
componentDidMount(){
//用户刷新之后,用户名输入自动获取焦点
this.input.focus();
};
render(){
return(
<div className='comment-input'>
<div className='comment-field'>
<span className='comment-field-name'>用户名:</span>
<div className='comment-field-input'>
<input
ref={(input)=>this.input=input}
value={this.state.username}
onBlur={this.handleUsernameHold}
onChange={this.handleUsernameChange}
/>
</div>
</div>
<div className='comment-field'>
<span className='comment-field-name'>评论内容:</span>
<div className='comment-field-input'>
<textarea
value={this.state.content}
onChange={this.handleContentChange}
/>
</div>
</div>
<div className='comment-field-button'>
<button onClick={this.handleSubmit}>
发布
</button>
</div>
</div>
)
}
}
export default CommentInput//给input标签绑定 ref={(input)=>{this.input = input}}
//用来直接获取dom节点的值,此处将input的值赋给this.input,让外部能访问
单条用户评论视图:Comment 所有内容
import {Component} from "react";
import React from "react";
class Comment extends Component{
constructor(){
super();
this.state ={
//初始化时间
timeString:''
}
}
//显示用户评论时间
handleTimeString=()=>{
const item=this.props.item;
//当前时间减去用户创建时的时间
const duration=(+Date.now()-item.createTime)/1000;
//如果足够60就转成分,不够60就转成秒
return duration>60?`${Math.round(duration/60)}分钟前`:`${Math.round(Math.max(duration,1))}秒前`;
};
//点击删除事件
//将handleDelete事件传出,index传出
handleDelete=()=>{
if(this.props.deleteItem){
this.props.deleteItem(this.props.index)
}
};
render(){
return(
<div className='comment'>
<div className='comment-user'>
<span className='comment-username'>{this.props.item.username} </span>:
</div>
<p>{this.props.item.content}</p>
<span className="comment-delete" onClick={this.handleDelete}>删除</span>
<span className="comment-createdtime">
{this.handleTimeString()}
</span>
</div>
)
}
}
export default Comment
评论列表 CommentList 所有内容
import {Component} from "react";
import React from "react";
import Comment from './Comment'
class CommentList extends Component{
constructor(){
super();
this.state ={
items:[]
}
}
//将数组列表传出,将deleteItem删除事件传出
render(){
return(
<div>
{this.props.items.map((item,index)=>
<Comment deleteItem={this.props.deleteItem}
item={item} index={index} key={index}
/>)}
</div>
)
}
}
export default CommentList复制代码
总组件CommentApp 的所有内容
import {Component} from "react";
import React from "react";
import CommentInput from './CommentInput'
import CommentList from './CommentList'
class CommentApp extends Component{
constructor(){
super();
this.state ={
items:[]
}
}
//点击发送
handleSubmit=(item)=>{
//点击发送时push当前那条
this.state.items.push(item);
//更新数据列表
this.setState({
items:this.state.items
});
//用户刷新时保存当前数据
localStorage.setItem('items',JSON.stringify(this.state.items))
};
//删除事件
handleDelete=(index)=>{
console.log(index);
//点击删除,删除当前
this.state.items.splice(index,1);
//列表数据更新至最新
this.setState({
items:this.state.items
});
//删除后保存当下数据
localStorage.setItem('items',JSON.stringify(this.state.items))
};
//装载前获取
componentWillMount(){
let items=localStorage.getItem('items');
if(items){
items=JSON.parse(items);
this.setState({items})
}
};
render(){
return(
<div className="wrapper">
<CommentInput submit={this.handleSubmit} />
<CommentList deleteItem={this.handleDelete} items={this.state.items}/>
</div>
)
}
}
export default CommentApp
// window.localStorage
// 保存数据语法:
// localStorage.setItem("key", "value");
// 读取数据语法:
// var lastname = localStorage.getItem("key");
// 删除数据语法:
// localStorage.removeItem("key");复制代码
index.js下所有内容:
import React from 'react';
import ReactDOM from 'react-dom';
import CommentApp from "./components/comment/CommentApp";
import './index.css'
ReactDOM.render(<CommentApp/>, document.getElementById('root'));
复制代码
index.css下所有样式内容:
body {
margin: 0;
padding: 0;
font-family: sans-serif;
background-color: #fbfbfb;
}
.wrapper {
width: 500px;
margin: 10px auto;
font-size: 14px;
background-color: #fff;
border: 1px solid #f1f1f1;
padding: 20px;
}
/* 评论框样式 */
.comment-input {
background-color: #fff;
border: 1px solid #f1f1f1;
padding: 20px;
margin-bottom: 10px;
}
.comment-field {
margin-bottom: 15px;
display: flex;
}
.comment-field .comment-field-name {
display: flex;
flex-basis: 100px;
font-size: 14px;
}
.comment-field .comment-field-input {
display: flex;
flex: 1;
}
.comment-field-input input,
.comment-field-input textarea {
border: 1px solid #e6e6e6;
border-radius: 3px;
padding: 5px;
outline: none;
font-size: 14px;
resize: none;
flex: 1;
}
.comment-field-input textarea {
height: 100px;
}
.comment-field-button {
display: flex;
justify-content: flex-end;
}
.comment-field-button button {
padding: 5px 10px;
width: 80px;
border: none;
border-radius: 3px;
background-color: #00a3cf;
color: #fff;
outline: none;
cursor: pointer;
}
.comment-field-button button:active {
background: #13c1f1;
}
/* 评论列表样式 */
.comment-list {
background-color: #fff;
border: 1px solid #f1f1f1;
padding: 20px;
}
/* 评论组件样式 */
.comment {
position: relative;
display: flex;
border-bottom: 1px solid #f1f1f1;
margin-bottom: 10px;
padding-bottom: 10px;
min-height: 50px;
}
.comment .comment-user {
flex-shrink: 0;
}
.comment-username {
color: #00a3cf;
font-style: italic;
}
.comment-createdtime {
padding-right: 5px;
position: absolute;
bottom: 0;
right: 0;
padding: 5px;
font-size: 12px;
}
.comment:hover .comment-delete {
color: #00a3cf;
}
.comment-delete {
position: absolute;
right: 0;
top: 0;
color: transparent;
font-size: 12px;
cursor: pointer;
}
.comment p {
margin: 0;
/*text-indent: 2em;*/
}
code {
border: 1px solid #ccc;
background: #f9f9f9;
padding: 0px 2px;
}
标签:comment,index,items,用户,React,案例,state,import,input From: https://blog.51cto.com/u_12422954/5986025