1.用戶可輸入用戶名css
2.輸入評論內容react
3.點擊發布數組
4.用戶名和用戶評論會被顯示在列表裏,第一個評論在最上面bash
5.且顯示本條評論離如今過去了多長時間app
6.鼠標放在事件上方可顯示刪除鍵,點擊刪除,刪除當前dom
1.components下建立comment文件夾flex
2.先建立用戶輸入組件:CommentInputui
3.再建立單條用戶評論視圖:Commentthis
4.接着建立CommentList組件,將用戶評論遍歷渲染成評論列表spa
5.建立CommentApp組件,將CommentInput評論組件和CommentList列表組件渲染到一塊兒
6.再index.js中引入展現
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,讓外部能訪問
複製代碼
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複製代碼
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複製代碼
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");複製代碼
import React from 'react';
import ReactDOM from 'react-dom';
import CommentApp from "./components/comment/CommentApp";
import './index.css'
ReactDOM.render(<CommentApp/>, document.getElementById('root'));
複製代碼
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;
}複製代碼