• react提供了一个用于创建react项目的脚手架库: create-react-app
  • 项目的整体技术架构为: react + webpack + es6 + eslint
  • 使用脚手架开发的项目的特点: 模块化, 组件化, 工程化

创建项目并启动

  1. npm install -g create-react-app
  2. create-react-app hello-react
  3. cd hello-react
  4. npm start

React 脚手架项目结构

  1. ReactNews
  2. |--node_modules---第三方依赖模块文件夹
  3. |--public
  4. |-- index.html-----------------主页面
  5. |--scripts
  6. |-- build.js-------------------build打包引用配置
  7. |-- start.js-------------------start运行引用配置
  8. |--src------------源码文件夹
  9. |--components-----------------react组件
  10. |--index.js-------------------应用入口js
  11. |--.gitignore------git版本管制忽略的配置
  12. |--package.json----应用包配置文件
  13. |--README.md-------应用描述说明的readme文件

例子

效果:

7.gif

代码结构:

src
 |_index.js
 |_components
   |_app.jsx
   |_commentAdd.jsx
   |_commentList.jsx
   |_commentItem.jsx

代码:

app.jsx

// app.jsx
class App extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
      comments: []
    }
    this.delete = this.delete.bind(this)
  }

  componentDidMount () {
    //模拟异步获取数据
    setTimeout(() => {
      const comments = [
        {
          username: "Tom",
          content: "ReactJS好难啊!",
          id: Date.now()
        },
        {
          username: "JACK",
          content: "ReactJS还不错!",
          id: Date.now() + 1
        }
      ]
      this.setState({
        comments
      })
    }, 1000)
  }

  add = (comment) => {
    let comments = this.state.comments
    comments.unshift(comment)
    this.setState({ comments })
  }

  delete (index) {
    let comments = this.state.comments
    comments.splice(index, 1)
    this.setState({ comments })
  }

  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">
          <CommentAdd add={this.add}/>
          <CommentList comments={this.state.comments} delete={this.delete}/>
        </div>
      </div>
    )
  }
}
export default App

commentAdd.jsx

import React from 'react'
import PropTypes from 'prop-types'

class CommentAdd extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
      username: '',
      content: ''
    }
    this.addComment = this.addComment.bind(this)
    this.changeUsername = this.changeUsername.bind(this)
    this.changeContent = this.changeContent.bind(this)
  }

  addComment () {
    // 根据输入的数据创建评论对象
    let { username, content } = this.state
    let comment = { username, content }
    // 添加到comments中, 更新state
    this.props.add(comment)
    // 清除输入的数据
    this.setState({
      username: '',
      content: ''
    })
  }

  changeUsername (event) {
    this.setState({
      username: event.target.value
    })
  }

  changeContent (event) {
    this.setState({
      content: event.target.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="用户名"
                   value={this.state.username} onChange={this.changeUsername}/>
          </div>
          <div className="form-group">
            <label>评论内容</label>
            <textarea className="form-control" rows="6" placeholder="评论内容"
              value={this.state.content} 
              onChange={this.changeContent}></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>
    )
  }
}
CommentAdd.propTypes = {
  add: PropTypes.func.isRequired
}
export default CommentAdd

commentList.jsx

import React from 'react'
import PropTypes from 'prop-types'
import CommentItem from '../comment-item/comment-item'
import './commentList.css'
class CommentList extends React.Component {
  constructor (props) {
    super(props)
  }

  render () {
    let comments = this.props.comments
    let display = comments.length > 0 ? 'none' : 'block'
    return (
      <div className="col-md-8">
        <h3 className="reply">评论回复:</h3>
        <h2 style={{ display: display }}>暂无评论,点击左侧添加评论!!!</h2>
        <ul className="list-group">
          {
            comments.map((comment, index) => {
              console.log(comment)
              return <CommentItem 
                       comment={comment} 
                       key={index} 
                       index={index} 
                       delete={this.props.delete}/>
            })
          }
        </ul>
      </div>
    )
  }
}
// 原型限制
CommentList.propTypes = {
  comments: PropTypes.array.isRequired,
  delete: PropTypes.func.isRequired
}
export default CommentList

commentItem.jsx

import React from 'react'
import PropTypes from 'prop-types'
import './commentItem.css'

class CommentItem extends React.Component {
  constructor (props) {
    super(props)
    this.deleteComment = this.deleteComment.bind(this)
  }

  deleteComment () {
    let username = this.props.comment.username
    if (window.confirm(`确定删除${username}的评论吗?`)) {
      this.props.delete(this.props.index)
    }
  }

  render () {
    let comment = this.props.comment
    return (
      <li className="list-group-item">
        <div className="handle">
          <a href="javascript:" onClick={this.deleteComment}>删除</a>
        </div>
        <p className="user"><span >{comment.username}</span><span>说:</span></p>
        <p className="centence">{comment.content}</p>
      </li>
    )
  }
}
CommentItem.propTypes = {
  comment: PropTypes.object.isRequired,
  index: PropTypes.number.isRequired,
  delete: PropTypes.func.isRequired
}
export default CommentItem

index.js

import React from 'react'
import ReactDOM from 'react-dom'
import App from './components/app/app'

ReactDOM.render(<App/>, document.getElementById('root'))