react组件化实现简易留言板
效果
实现
可以拆分为三个组件,input组件,button组件,list组件
1.input组件
input组件实现昵称的输入框和留言内容的输入框,通过判断父组件上是否传了row属性来判断是展示位单行输入框还是文本域输入框。
这两种输入框上面都有一个OnInput事件,用来获取当前输入框的值。
import React,{
Fragment} from 'react'
export default function Input(props) {
let inputValue = function(e){
//触发父组件上面的inputValue事件,并把e.target.value(当前输入框的值)传给父组件。
props.inputValue(e.target.value)
}
let input = null;
if(!props.row){
input = <input onInput={
inputValue}></input>
}else{
input = <textarea rows="5" cols="30" onInput={
inputValue}></textarea>
}
return (
<Fragment>
{
input }
</Fragment>
)
}
2.button组件
button组件用来实现提交按钮。
import React from 'react'
export default function Button(props) {
let handelSubmit = function(){
//触发父组件上面的onSubmit事件,
props.onSubmit()
}
return (
<div>
<button onClick={
handelSubmit}>提交</button>
</div>
)
}
3.list组件
list组件用来实现留言内容的遍历展示。
首先判断当前要遍历的数组是否有值,然后有值的话,就遍历当前事件数组。
import React from 'react'
export default function List(props) {
let comment = null;
if(!props.data || props.data.length === 0){
comment = <p style={
{
textAlign:'center'}}>还没有留言!</p>
}else{
comment = props.data.map((item,index) => {
return(
<div className="comment-item" key={
index}>
<div className="name">
昵称:<span>{
item.name}</span>
时间:<span>{
item.time}</span>
</div>
<div className="content">
内容:{
item.content}
</div>
<div className="star">
<span onClick={
() => {
props.addStar(item,index)
}}>赞({
item.star})</span>
</div>
</div>
)
})
}
return (
<div>
{
comment}
</div>
)
}
4.App.jsx
App.jsx是父组件。
import React, {
Component } from 'react';
import Button from './Button';
import Input from './Input';
import List from './List';
import './App.css'
class App extends Component {
constructor(){
super();
this.state = {
name : '',
content : '',
lists : []
}
this.userName = this.userName.bind(this);
this.userContent = this.userContent.bind(this);
this.submit = this.submit.bind(this);
this.onStar = this.onStar.bind(this)
}
render() {
let {
lists} = this.state;
return (
<div>
{
/* 留言列表 */}
<List data={
lists} addStar={
this.onStar}></List>
{
/* 留言操作区 */}
<div className="comment">
<div className="name">
<span>昵称:</span>
<Input inputValue={
this.userName}></Input>
</div>
<div className="content">
<span>内容:</span>
<Input row inputValue={
this.userContent}></Input>
</div>
<Button onSubmit={
this.submit}></Button>
</div>
</div>
);
}
//输入昵称
//更新视图,实现数据的双向绑定,参数为子组件上的默认参数
userName(val){
this.setState({
name : val
})
}
//输入姓名
//更新视图,实现数据的双向绑定,参数为子组件上的默认参数
userContent(val){
this.setState({
content : val
})
}
//提交事件
//点击提交按钮的时候,往要遍历的数组中push一个对象,把name,time,content,star都传进去。
submit(){
let lists = this.state.lists;
lists.push({
name : this.state.name, //name为当前state对象里面的name,是输入昵称事件绑定的数据
time : this.getTime(), //time是调用了一个自定义函数
content : this.state.content, //content为当前state对象里面的content,是输入留言内容事件绑定的数据
star : 0 //star默认值为0
})
//更新视图 一定要记得,不是吧值push进list就没事了,一定呀更新视图,才能调用render()函数来更新视图
this.setState({
lists
})
console.log(this.state.lists)
}
//点赞事件
//参数为子组件上的默认事件,item是当前要点赞的对象,index是当前要点赞对象的下标。首先获取到当前要点赞对象的副本,然后让它的点赞数加1,然后再把当前对象删除,并把新的对象传进去。
onStar(item,index){
let obj = item;
obj.star ++;
let lists = this.state.lists;
lists.splice(index,1,obj);
//更新视图
this.setState({
lists
})
}
//获取时间
getTime(){
let d = new Date();
return `${
d.getFullYear()}-${
d.getMonth()+1}-${
d.getDate()} ${
d.getHours()}:${
d.getMinutes()}`
}
}
export default App;
5.index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App'
ReactDOM.render(
<App />,
document.getElementById('root')
);
需要注意的就是,state里面有name,content,是输入事件双向绑定的数据,以及list数组对象,是提交按钮push进去的对象,里面有留言展示区域要展示的所有内容。