React评论展示案例(包含知识点:state、props、ref、React声明周期、localStorage本地存储等)
本案例在上一篇的案例(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本地存储等)的更多相关文章
- React基础篇(2) -- state&props&refs
内容简介 state props refs 行内样式及动态类名 state 基本介绍 React 把组件看成是一个状态机(State Machines).通过与用户的交互,实现不同状态,然后渲染 UI ...
- (尚030)Vue_案例_存储数据(localStorage本地存储技术)
当刷新页面时,会变为原来的状态 1.问题:当我刷新是不希望改变原来状态 需要缓存我当前的数据 2.究竟是缓存在内存里还是在文件里??? 缓存在文件里,因为浏览器关闭了,内存就没了;而我们需要重新打开浏 ...
- 从 0 到 1 实现 React 系列 —— 2.组件和 state|props
看源码一个痛处是会陷进理不顺主干的困局中,本系列文章在实现一个 (x)react 的同时理顺 React 框架的主干内容(JSX/虚拟DOM/组件/生命周期/diff算法/setState/ref/. ...
- react基础语法(五) state和props区别和使用
props的验证: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> < ...
- React 三大属性state,props,refs以及组件嵌套的应用
React 三大属性state,props,refs以及组件嵌套的应用 该项目实现了一个简单的表单输入添加列表的内容 代码如下 <!DOCTYPE html> <html> & ...
- react 也就这么回事 05 —— 组件 & Props
什么是组件:用来实现局部功能的可复用代码片段 比如很多界面会用到"分页"功能,因此可以将它封装成独立的组件 这样用到分页的界面只需引入该组件而不必重新写代码 1 定义组件 在 Re ...
- react 入坑笔记(三) - Props
React Props props - 参数. 组件类 React.Component 有个 defaultProps 属性,以 class xxx extend React.Component 形式 ...
- React文档(六)state和生命周期
想一下之前的章节时钟的例子. 目前为止我们只学习了一直方式去更新UI. 我们调用ReactDOM.render()方法去改变渲染的输出: function tick() { const element ...
- 前端笔记之React(二)组件内部State&React实战&表单元素的受控
一.组件内部的State 1.1 state state叫状态,是每一个类式组件都有的属性,但函数式组件,没有state. state是一个对象,什么值都可以定义. 在任何类式组件的构造函数中,可以用 ...
随机推荐
- powerdesigner导出sql
http://jingyan.baidu.com/article/7082dc1c48960ee40a89bd38.html 生成注释 http://wangjingyi.iteye.com/blog ...
- POJ Oulipo KMP 模板题
http://poj.org/problem?id=3461 Oulipo Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4 ...
- Flex之文件目录浏览器实例
Flex之文件目录浏览器实例 Flex的AIR项目 <?xml version="1.0" encoding="utf-8"?> <mx:Wi ...
- nodejs操作文件和数据流
前言 node中有一组流api,它们可以像处理网络流一样处理文件.流api用起来非常方便,本节学习介绍文件处理基础和流的概念. 目录 处理文件路径 fs核心模块简介 操作流 慢客户端问题 1. 处理文 ...
- OpenJDK源码研究笔记(十二):JDBC中的元数据,数据库元数据(DatabaseMetaData),参数元数据(ParameterMetaData),结果集元数据(ResultSetMetaDa
元数据最本质.最抽象的定义为:data about data (关于数据的数据).它是一种广泛存在的现象,在许多领域有其具体的定义和应用. JDBC中的元数据,有数据库元数据(DatabaseMeta ...
- ArcGIS engine中Display类库 (局部刷新)
转自原文 ArcGIS engine中Display类库 (局部刷新) Display类库包括了用于显示GIS数据的对象.除了负责实际输出图像的主要显示对象(display object)外,这个类库 ...
- elasticsearch index 之 engine
elasticsearch对于索引中的数据操作如读写get等接口都封装在engine中,同时engine还封装了索引的读写控制,如流量.错误处理等.engine是离lucene最近的一部分. engi ...
- 5.brackets 快捷键 有大用
转自:https://blog.csdn.net/u012011360/article/details/41209223 ctrl+b 当选中一个文本时,会出现相同的文本,被高亮显示 按ctrl+b ...
- vue -- 脚手架之webpack.dev.conf.js
webpack.dev.conf.js 开发环境模式配置文件: 'use strict'//js按照严格模式执行 const utils = require('./utils')//导入utils. ...
- HTML 页面内容禁止选中
写一个小笔记,怎么禁止HTML页面不被选中,复制. CSS: *{ moz-user-select: -moz-none; -moz-user-select: none; -o-user-select ...