第三章 react应用(基于react脚手架)
使用create-react-app创建react应用
react脚手架
-
xxx 脚手架:用来帮助程序员快速创建一个基于 xxx 库的模板项目
-
包含了所有需要的配置
-
指定好了所有的依赖
-
可以直接安装/编译/运行一个简单效果
-
-
react 提供了一个用于创建 react 项目的脚手架库:
create-react-app
-
项目的整体技术架构为:react + webpack + es6 + eslint
-
使用脚手架开发的项目的特点:模块化,组件化,工程化
创建并启动
// 全局安装create-react-app脚手架
npm i -g create-react-app
// 创建一个react项目,项目名称是hello-react
create-react-app hello-react
// 进入hello-react
cd hello-react
// 启动项目
npm start
react脚手架项目结构
-
node_modules – 第三方依赖模块文件夹
-
public
- index.html – 主页面
-
scripts
- build.js – build打包引用配置
- start.js – start运行引用配置
-
src – 源码文件夹
- components – react组件
- index.js – 应用入口js
-
.gitignore – git版本管制忽略的配置
-
package.json – 应用包配置文件
-
README.md – 应用描述说明的readme文件
案例 – 评论管理
- app.jsx
import React, {Component} from 'react'
import CommentAdd from "../comment-add/comment-add";
import CommentList from "../comment-list/comment-list";
export default class App extends Component {
//给组件对象指定state属性(简写)
state = {
comments: [
{username: 'Tom', content: 'React挺好的!'},
{username: 'Jack', content: 'React太难了!'}
]
}
// 添加评论
addComment = (comment) => {
// 收集数据
const {comments} = this.state
comments.unshift(comment)
// 更新状态
this.setState({comments})
}
// 删除指定评论
deleteComment = (index) => {
// 收集数据
const {comments} = this.state
// splice可以实现增删改
comments.splice(index, 1)
// 更新状态
this.setState({comments})
}
render() {
const {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">
<div className="row">
<CommentAdd addComment={this.addComment}/>
<CommentList comments={comments} deleteComment={this.deleteComment}/>
</div>
</div>
</div>
);
}
}
- comment-add.jsx
import React,{Component} from 'react'
import PropsTypes from 'prop-types'
export default class CommentAdd extends Component{
static propsTypes={
addComment:PropsTypes.func.isRequired
}
state = {
usename:'',
content:''
}
// 点击提交事件
handleSubmit = (event) => {
//1. 收集数据,并封装为comment对象
const comment = this.state
//2. 更新状态
this.props.addComment(comment)
//3.清除数据
this.setState({
username:'',
content:''
})
// 阻止事件的默认行为(提交)
event.preventDefault()
//数据在那个组件,更新数据的行为就应该在那个组件
}
handleNameChange = (event) =>{
const username = event.target.value
this.setState({username})
}
handleContentChange = (event) =>{
const content = event.target.value
this.setState({content})
}
render() {
const {username,content} = this.state
return (
<div className="col-4">
<form className="form-horizontal">
<div className="form-group">
<label>用户名</label>
<input type="text" className="form-control" placeholder="用户名" name="username"
value={username} onChange={this.handleNameChange}/>
</div>
<div className="form-group">
<label>评论内容</label>
<textarea className="form-control" rows="6" placeholder="评论内容" name="content"
value={content} onChange={this.handleContentChange}></textarea>
</div>
<div className="form-group">
<div className="col-sm-offset-2 col-sm-10">
<button className="btn btn-primary pull-right" onClick={this.handleSubmit}>提 交</button>
</div>
</div>
</form>
</div>
);
}
}
-
comment-item
- comment-item.jsx
import React, {Component} from 'react' import PropTypes from 'prop-types' import './commentItem.css' export default class CommentItem extends Component { //定义约束 static propTypes = { comment: PropTypes.object.isRequired, deleteComment: PropTypes.func.isRequired, index: PropTypes.number.isRequired } handleDelete = () => { const {comment, deleteComment, index} = this.props // 提示 if (window.confirm(`确定删除${comment.username}的评论吗?`)) { // 确定后删除 deleteComment(index) } } render() { // 取数据 const {comment} = this.props return ( <li className="list-group-item"> <div className="handle"> <button className="btn btn-danger" onClick={this.handleDelete}>删除</button> </div> <p className="user"><span>{comment.username}</span>说:</p> <p className="centence">{comment.content}</p> </li> ); } }
- commentItem.css
li { transition: .5s; overflow: hidden; } .handle { width: 40px; border: 1px solid #ccc; background: #fff; position: absolute; right: 10px; top: 1px; text-align: center; } .handle a { display: block; text-decoration: none; } .list-group-item .centence { padding: 0px 50px; } .user { font-size: 22px; }
-
comment-list
- comment-list.jsx
import React, {Component} from 'react' import PropTypes from 'prop-types' import './comment-list.css' import CommentItem from "../comment-item/comment-item"; export default class CommentList extends Component { //给组件类指定属性 static proTypes = { comments: PropTypes.array.isRequired, deleteComment: PropTypes.func.isRequired } render() { const {comments, deleteComment} = this.props // 计算出是否显示 const display = comments.length === 0 ? 'block' : 'none' return ( <div className="col-8"> <h3 className="reply">评论回复:</h3> <h2 style={{display}}>暂无评论,点击上方添加评论!!!</h2> <ul className="list-group"> { comments.map((comment, index) => <CommentItem comment={comment} key={index} deleteComment={deleteComment} index={index}/>) } </ul> </div> ); } }
- comment-list.css
.reply { margin-top: 0px; }
-
入口文件app.jsx
import React, {Component} from 'react'
import logo from '../logo.svg'
export default class App extends Component {
render() {
return (
<div>
<img className='logo' src={logo} alt="加载中..."/>
<p className='react_p'>React app组件</p>
</div>
);
}
}
- index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from "./compontents/app/app";
ReactDOM.render(<App/>,document.getElementById('root'))