本案例在上一篇的案例(React组件之间通过Props传值的技巧(小案例,帮助体会理解props、state、受控组件和非受控组件等))的基础上加强功能和用户体验,但是当然还有很多需要改进的地方,后期一步步慢慢增强:

import React,{Component} from 'react';
import {render} from 'react-dom';
import './index.css'; 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()
})
}
this.setState({
content:''
})
}; handleUsernameHold=(event)=>{
localStorage.setItem('username',event.target.value)
}; componentWillMount(){
const username=localStorage.getItem('username');
if(username){
this.setState({username})
}
} 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>
)
}
} class CommentList extends Component{ constructor(){
super();
this.state={
items:[]
}
} render(){
return(
<div>
{this.props.items.map((item,index)=><Comment deleteItem={this.props.deleteItem} item={item} index={index} key={index}/>)}
</div>
)
}
} class Comment extends Component{
constructor(){
super();
this.state={
timeString:''
}
} handleTimeString=()=>{
const item=this.props.item;
const duration=(+Date.now()-item.createTime)/1000;
return duration>60?`${Math.round(duration/60)}分钟前`:`${Math.round(Math.max(duration,1))}秒前`;
}; 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>
)
}
} class CommentApp extends Component{
constructor(){
super();
this.state={
items:[]
}
} handleSubmit=(item)=>{
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>
)
}
} class Index extends Component{
render(){
return(
<div>
<CommentApp/>
</div>
)
}
} render(<Index/>,document.getElementById('root'));
body {
margin:;
padding:;
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:;
} .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:;
} .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:;
} .comment-username {
color: #00a3cf;
font-style: italic;
} .comment-createdtime {
padding-right: 5px;
position: absolute;
bottom:;
right:;
padding: 5px;
font-size: 12px;
} .comment:hover .comment-delete {
color: #00a3cf;
} .comment-delete {
position: absolute;
right:;
top:;
color: transparent;
font-size: 12px;
cursor: pointer;
} .comment p {
margin:;
/*text-indent: 2em;*/
} code {
border: 1px solid #ccc;
background: #f9f9f9;
padding: 0px 2px;
}

React评论展示案例(包含知识点:state、props、ref、React声明周期、localStorage本地存储等)的更多相关文章

  1. React基础篇(2) -- state&props&refs

    内容简介 state props refs 行内样式及动态类名 state 基本介绍 React 把组件看成是一个状态机(State Machines).通过与用户的交互,实现不同状态,然后渲染 UI ...

  2. (尚030)Vue_案例_存储数据(localStorage本地存储技术)

    当刷新页面时,会变为原来的状态 1.问题:当我刷新是不希望改变原来状态 需要缓存我当前的数据 2.究竟是缓存在内存里还是在文件里??? 缓存在文件里,因为浏览器关闭了,内存就没了;而我们需要重新打开浏 ...

  3. 从 0 到 1 实现 React 系列 —— 2.组件和 state|props

    看源码一个痛处是会陷进理不顺主干的困局中,本系列文章在实现一个 (x)react 的同时理顺 React 框架的主干内容(JSX/虚拟DOM/组件/生命周期/diff算法/setState/ref/. ...

  4. react基础语法(五) state和props区别和使用

    props的验证: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> < ...

  5. React 三大属性state,props,refs以及组件嵌套的应用

    React 三大属性state,props,refs以及组件嵌套的应用 该项目实现了一个简单的表单输入添加列表的内容 代码如下 <!DOCTYPE html> <html> & ...

  6. react 也就这么回事 05 —— 组件 & Props

    什么是组件:用来实现局部功能的可复用代码片段 比如很多界面会用到"分页"功能,因此可以将它封装成独立的组件 这样用到分页的界面只需引入该组件而不必重新写代码 1 定义组件 在 Re ...

  7. react 入坑笔记(三) - Props

    React Props props - 参数. 组件类 React.Component 有个 defaultProps 属性,以 class xxx extend React.Component 形式 ...

  8. React文档(六)state和生命周期

    想一下之前的章节时钟的例子. 目前为止我们只学习了一直方式去更新UI. 我们调用ReactDOM.render()方法去改变渲染的输出: function tick() { const element ...

  9. 前端笔记之React(二)组件内部State&React实战&表单元素的受控

    一.组件内部的State 1.1 state state叫状态,是每一个类式组件都有的属性,但函数式组件,没有state. state是一个对象,什么值都可以定义. 在任何类式组件的构造函数中,可以用 ...

随机推荐

  1. C#读写config配置文件--读取配置文件类

    一:通过Key访问Value的方法: //判断App.config配置文件中是否有Key(非null) if (ConfigurationManager.AppSettings.HasKeys()) ...

  2. 玲珑杯 Round #18 A -- 计算几何你瞎暴力

    因为坐标都在1-10之间,因此可暴力求解 #include <iostream> #include <cstdio> #include <cstring> #inc ...

  3. UESTC 1599 wtmsb

    这天,AutSky_JadeK看到了n张图片,他忍不住说道:“我TM社保!”. 每张图片有一个社保值,他可以合并两张图片,合并所得的图片的社保值是原来两张图片的社保值之和. 每次合并需要消耗的体力也是 ...

  4. 【Henu ACM Round #13 F】Fibonacci-ish

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举序列的头两个数字是什么 O(N^2) 然后头两个数字确定之后. f[3],f[4]..就确定了 只需查看f[3],f[4]..是 ...

  5. Unity容器实现自动注册

    如何创建Unity容器? 首先NuGet搜索Unity, 该示例中使用的版本为4.0.1 新建控制台程序 示例中使用常规操作, 创建一个IPay接口, 分别有两个实现类: ApplePay.Huawe ...

  6. IOS开发人员经常使用的10个Xcode插件

    IOS开发人员经常使用的10个Xcode插件 申请达人,去除赞助商链接 一个合适的插件意味着它能够适应不同的开发环境,Sublime Text 和TextMate就是非常好的样例.你知道Xcode也支 ...

  7. BRep Shapes Based on Tessellated Geometry

    BRep Shapes Based on Tessellated Geometry eryar@163.com Key Words. BRep Shape, Tessellated Geometry, ...

  8. [UnityUI]循环滑动列表

    效果图: 使用的是UGUI和DOTween 当中比較关键的是循环滑动和层次排序: 1.循环滑动:这里先如果显示五张图片.分别标记为0,1,2,3,4,那么当向左滑动时,序列就变为1,2,3,4,0,这 ...

  9. 第8章7节《MonkeyRunner源代码剖析》MonkeyRunner启动执行过程-小结

    最后我们对MonkeyRunner启动的过程做一个总结,当然,当中也包括启动Monkey,尽管它不属于启动过程的一部分: monkeyrunner这个shell脚本会先设置一些执行环境的系统属性保存到 ...

  10. 通过Debug-->Attach to Process的方式来调试网站

    找到网站所对应的应用程序池