使用create-react-app创建react应用
react脚手架
1) xxx脚手架: 用来帮助程序员快速创建一个基于xxx库的模板项目
a. 包含了所有需要的配置
b. 指定好了所有的依赖
c. 可以直接安装/编译/运行一个简单效果
2) react提供了一个用于创建react项目的脚手架库: create-react-app
3) 项目的整体技术架构为: react + webpack + es6 + eslint
4) 使用脚手架开发的项目的特点: 模块化, 组件化, 工程化
创建项目并启动
npm i create-react-app -g
create-react-app hello-react
cd hello-react
yarn start
运行后效果:
demo:评论管理
效果:
完成项目的静态组件
- 1.准备工作
下载静态页面 -
2.使用
create-react-app
生成脚手架
create-react-app comment-demo
cd comment-demo
生成脚手架后的目录结构如下图所示:
删除用不上的文件,以免干扰:
- 3.拆分组件
入口文件:index.js
应用组件: App.jsx
添加评论组件: Add.jsx
评论列表组件: List.jsx
评论项组件: Item.jsx
src/index.js
内容如下:
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
ReactDOM.render(<App/>,document.getElementById('root'))
src/App.jsx
内容如下:
import React, {Component} from 'react'
import Add from './components/add/Add'
import List from './components/list/List'
export default class App extends Component {
render() {
return (
<div>
<header className="site-header jumbotron">
<div className="container">
<div className="row">
<div className="col-xs-12">
<h1>请发表对React的评论</h1>
</div>
</div>
</div>
</header>
<div className="container">
<Add/>
<List/>
</div>
</div>
)
}
}
src/components/add/Add.jsx
内容如下:
import React, {Component} from 'react'
export default class Add extends Component {
render() {
return (
<div className="col-md-4">
<form className="form-horizontal">
<div className="form-group">
<label>用户名</label>
<input type="text" className="form-control" placeholder="用户名"/>
</div>
<div className="form-group">
<label>评论内容</label>
<textarea className="form-control" rows="6" placeholder="评论内容"></textarea>
</div>
<div className="form-group">
<div className="col-sm-offset-2 col-sm-10">
<button type="button" className="btn btn-default pull-right">提交</button>
</div>
</div>
</form>
</div>
)
}
}
src/components/item/Item.jsx
内容如下:
import React, {Component} from 'react'
import './Item.css'
export default class Item extends Component {
render() {
return (
<li className="list-group-item">
<div className="handle">
<a href="#1">删除</a>
</div>
<p className="user"><span>xxx</span><span>说:</span></p>
<p className="centence">React不错!</p>
</li>
)
}
}
src/components/list/List.jsx
内容如下:
import React, {Component} from 'react'
import Item from "../item/Item";
import './List.css'
export default class List extends Component {
render() {
return (
<div className="col-md-8">
<h3 className="reply">评论回复:</h3>
<h2 style={{display: 'none'}}>暂无评论,点击左侧添加评论!!!</h2>
<ul className="list-group">
<Item/>
</ul>
</div>
)
}
}
需要注意style内联样式的写法:
style={{display: 'none'}}
public/index.html
内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="stylesheet" href="%PUBLIC_URL%/css/bootstrap.css">
<title>React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
完整目录结构如下图:
动态初始化显示
首先实现右侧评论列表的动态显示
用状态来保存右侧的评论数据,由于Add
组件与List
组件都要用到,那么将此状态写在App
上。App.jsx
代码如下:
import React, {Component} from 'react'
import Add from './components/add/Add'
import List from './components/list/List'
export default class App extends Component {
state = {
comments: [
{userId: '001', userName: '张三', content: '你好啊,react'},
{userId: '002', userName: '李四', content: '大家好,我是002'},
{userId: '003', userName: '周杰伦', content: '麻烦给我的爱人一杯Mojito'},
]
}
render() {
let {comments} = this.state
return (
<div>
<header className="site-header jumbotron">
<div className="container">
<div className="row">
<div className="col-xs-12">
<h1>请发表对React的评论</h1>
</div>
</div>
</div>
</header>
<div className="container">
<Add/>
<List comments={comments}/>
</div>
</div>
)
}
}
List.jsx
代码如下:
import React, {Component} from 'react'
import Item from "../item/Item";
import './List.css'
export default class List extends Component {
render() {
let {comments} = this.props
return (
<div className="col-md-8">
<h3 className="reply">评论回复:</h3>
<h2 style={{display: 'none'}}>暂无评论,点击左侧添加评论!!!</h2>
<ul className="list-group">
{
comments.map((item)=>{
return <Item {...item}/>
})
}
</ul>
</div>
)
}
}
Item.jsx
代码如下:
import React, {Component} from 'react'
import './Item.css'
export default class Item extends Component {
render() {
let {userId,userName,content} = this.props
return (
<li className="list-group-item">
<div className="handle">
<a href={userId}>删除</a>
</div>
<p className="user"><span>{userName}</span><span>说:</span></p>
<p className="centence">{content}</p>
</li>
)
}
}
实现后效果:
完成评论新增功能
- 1.为
Add.jsx
中的提交按钮绑定addComment方法
import React, {Component} from 'react'
import {v1 as uuid} from 'uuid'
export default class Add extends Component {
addComment = () => {
//1.获取填写的内容
let {userName, content} = this
userName = userName.value
content = content.value
//2.验证内容合法性
if (userName === '' || content === '') {
alert('请填写姓名或内容')
return
}
//3生成uuid
let userId = uuid()
//4.更新状态
let {setComments} = this.props
setComments({userId, userName, content})
//5.清空输入框里的内容
this.userName.value = ''
this.content.value = ''
}
render() {
return (
<div className="col-md-4">
<form className="form-horizontal">
<div className="form-group">
<label>用户名</label>
<input type="text" className="form-control" placeholder="用户名" ref={(input) => {
this.userName = input
}}/>
</div>
<div className="form-group">
<label>评论内容</label>
<textarea className="form-control" rows="6" placeholder="评论内容" ref={(input) => {
this.content = input
}}></textarea>
</div>
<div className="form-group">
<div className="col-sm-offset-2 col-sm-10">
<button type="button" className="btn btn-default pull-right" onClick={this.addComment}>提交
</button>
</div>
</div>
</form>
</div>
)
}
}
注意:uuid使用了第三方组件,需要先使用yarn add uuid
安装
- 2.在
App.jsx
中的增加更新状态方法,并将该方法传递到Add组件
import React, {Component} from 'react'
import Add from './components/add/Add'
import List from './components/list/List'
export default class App extends Component {
state = {
comments: [
]
}
setComments = (commentObj) => {
//获取原评论数据
let {comments} = this.state
//插入新评论数据
comments.unshift({...commentObj})
//更新状态
this.setState({comments})
}
render() {
let {comments} = this.state
return (
<div>
<header className="site-header jumbotron">
<div className="container">
<div className="row">
<div className="col-xs-12">
<h1>请发表对React的评论</h1>
</div>
</div>
</div>
</header>
<div className="container">
<Add setComments={this.setComments}/>
<List comments={comments}/>
</div>
</div>
)
}
}
- 3.在
List.jsx
里判断评论条数,没有则显示“暂无评论”
import React, {Component} from 'react'
import Item from "../item/Item";
import './List.css'
export default class List extends Component {
render() {
let {comments} = this.props
return (
<div className="col-md-8">
<h3 className="reply">评论回复:</h3>
<h2 style={{display: comments.length>0 ? 'none' : 'block'}}>暂无评论,点击左侧添加评论!!!</h2>
<ul className="list-group">
{
comments.map((item)=>{
return <Item key={item.userId} {...item}/>
})
}
</ul>
</div>
)
}
}
完成评论删除功能
- 1.在
App.jsx
中增加delComments
方法用于删除评论
delComments = (userId) => {
//获取原评论数据
let comments = [...this.state.comments]
//删除指定userId数据
comments.forEach((item,index)=>{
if(item.userId===userId){
comments.splice(index,1)
}
})
//更新状态
this.setState({comments})
}
在List组件中绑定delComments
方法:
<List comments={comments} delComments={this.delComments}/>
- 2.在
List.jsx
中的Item
组件传递delComments
方法
return <Item key={item.userId} delComments={delComments} {...item}/>
- 3.在
Item.jsx
中增加delete
方法用于执行删除操作
delete = () => {
let {userId,delComments} = this.props
delComments(userId)
}
<a href="#1" onClick={this.delete}>删除</a>