首页 > 其他分享 >React 小案例 用户评论

React 小案例 用户评论

时间:2023-01-03 15:34:45浏览次数:42  
标签:comment index items 用户 React 案例 state import input


功能展示 :

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

相关文章

  • React 用axios 获取遍历json 引入swiper轮播图
    结构展示:功能展示:1.使用swiper轮播插件,2.自动轮播,当前图片高亮小按钮首先引入swiper和配置环境1.npminstall--saveswiper2.在src文件夹index.js下引入样式,避免打包失败im......
  • CentOS 7 使用单用户模式解决不能登陆问题
    1.CentOS7系统开机时选择默认第一启动项,按字母"e"键编辑启动项;2.使用键盘上下左右方向键,往下找到linux16开头的一行,定位到ro(readonly);3.编辑ro为rw(readwri......
  • 记录报错 react Expected an assignment or function call and instead saw an expres
    报错:Expectedanassignmentorfunctioncallandinsteadsawanexpression no-unused-expressionsSearchforthekeywordstolearnmoreabouteacherror.期望一......
  • react Router 学习
     功能:1.进入项目后的默认路径是home,默认展示首页模块2.点击路由,切换子组件3.点击文章路由,根据传值不同进入三级详情路由,同时二级路由不显示4.点击返回首页,跳转到首页 安装......
  • 使用拦截器拦截未认证用户请求-将你拒之门外
    拦截器将用户的某个请求前中后进行插入相应操作。preHandle调用时间:Controller方法处理之前执行顺序:链式Intercepter情况下,Intercepter按照声明的顺序一个接一个执行......
  • react todolist 3
    功能:1.输入框输入事项,点击add,list增加一条,输入框清空并且聚焦;2.点击当前checkbox,勾选文字为已完成,取消勾选文字为未完成;父组件TodoList.js分成了三个子组件TodoHeader,TodoI......
  • react 做一个点赞按钮组件
      创建组件Like.js一开始设置为黑色false,isLiked如果为true渲染红心,false渲染黑心setState时用了两种方法importReact,{Component}from'react'exportdefaultclass......
  • react 渲染富文本中的标签内容
    假设拉取下来的是富文本携带html标签的内容应该如何渲染到页面:例:<div>我是富文本内容</div>在标签上使用dangerouslySetInnerHTML={{__html:this.state.article}}importRea......
  • react 中使用less
    首先npm install less-loader less --save -dev安装之后终端npm run eject   来暴露webpack的配置文件,如果报错:Removeuntrackedfiles,stashorcommitanych......
  • react 日常工作小笔记
    默认配置defaultProps默认配置通过 ​​||​​​ 操作符可以实现,React.js也提供了一种方式 ​​defaultProps​​,可以方便的做到默认配置。classLikeButtonextendsC......