react学习笔记(2)

1、React复习

// vscode在js文件中,对jsx语法非常友好
const element = (
  <div>
    {/* 我是注释 */}
    <h1>这是一个标题</h1>
    <p>这是内容</p>
  </div>
)

// react的组件: 函数组件    类组件
function Hello() {
  return <div>hello react</div>
}

class World extends React.Component {
  // 类组件一定需要有一个方法,render
  constructor(props) {
    super(props)
    // 类组件中,可以通过state属性,提供一些状态
    this.state = {
      msg: '哈哈'
    }
  }
  render() {
    return (
      <div>
        这是world组件---
        {this.state.msg} --- {this.props.name}
      </div>
    )
  }
}

// 函数组件和类组件的区别
// 函数组件:无状态组件
// 类组件: 状态组件, 在类组件中,可以有自己的状态
// 将来,如果某个组件不需要有自己状态,这个组件的内容是固定死的,直接使用函数组件就行
// 如果组件有自己的状态,需要定义一个类组件即可。
ReactDOM.render(<World name="zs" age="18" />, document.getElementById('app'))

2、React事件

// 1. 在react中注册事件与给DOM注册事件基本是一样的, onclick onmouseenter onblur onkeyup
// 2. 在react中注册事件,采用驼峰命名法, onClick onMouseEnter onBlur
// 3. 在react中注册事件,通过{}传入的是一个函数, 而不是一个字符串
// 4. 在react中,如果想要组件浏览器的默认行为,不要使用return false,使用e.preventDefault()
class Event extends React.Component {
  render() {
    return (
      <div>
        <button onClick={this.clickFn}>点我注册事件</button>
        <a href="http://web.itcast.cn" onClick={this.clickFn}>
          传智大前端
        </a>
      </div>
    )
  }

  clickFn(e) {
    // 想要组件浏览器的默认行为
    e.preventDefault()
    console.log('哈哈')
  }
}

ReactDOM.render(<Event />, document.getElementById('app'))

3、React事件-this的问题

// 在react的事件处理程序中,内部的this是指向undefined
// 解决方案1:  通过this.clickFn.bind(this)
// 解决方案2:  属性初始化器语法, 提供了一个箭头函数
// 解决方案3:  在函数外面包一层箭头函数  onClick={this.clickFn}
//  onClick={()=>{this.clickFn()}}

class Event extends React.Component {
  constructor(props) {
    super(props)

    // 提供组件自己的状态
    this.state = {
      msg: 'hello react'
    }

    // 可以在构造函数中,去处理事件处理函数的this问题
    // this.clickFn = this.clickFn.bind(this)
  }
  render() {
    return (
      <div>
        <p>{this.state.msg}</p>
        {/* 需求:点击button的时候,需要改变msg的数据 */}
        <button
          onClick={() => {
            this.clickFn()
          }}
        >
          点我修改msg
        </button>
        <a href="" onClick={this.clickFn} />
      </div>
    )
  }

  clickFn() {
    // 修改msg的数据
    // 注意点: 在react注册事件的时候,提供的事件处理函数的内部this指向undefined
    // 没办法访问到this,没有办法访问到当前实例,没有办法访问到数据
    // 如果想要修改react的状态,不能直接通过this.state.xxx去修改
    this.setState({
      msg: '呵呵'
    })
  }
}

ReactDOM.render(<Event />, document.getElementById('app'))

// bind方法: 任何一个函数,都有bind方法,bind方法可以用来修改函数内部的this指向
// call apply
// function fn(){}   fn.bind(obj)

4、React事件-传参的问题

// 在注册事件的时候,能够传递参数
class Event extends React.Component {
  constructor(props) {
    super(props)
  }
  render() {
    return (
      <div>
        <ul>
          <li>
            {/* 能够把id传递过来 */}
            <button
              onClick={() => {
                this.clickFn(1)
              }}
            >
              删除1
            </button>
          </li>
          <li>
            <button
              onClick={() => {
                this.clickFn(2)
              }}
            >
              删除2
            </button>
          </li>
          <li>
            <button>删除3</button>
          </li>
        </ul>
      </div>
    )
  }

  // 传参第一种: 通过bind的方式进行传参,还想要获取事件对象, 事件对象是最后一个参数
  // 参数第二种: 通过给事件处理程序包裹一个箭头函数
  clickFn(id) {
    console.log(id)
  }
}

ReactDOM.render(<Event />, document.getElementById('app'))

5、React条件渲染

// 条件渲染: 根据不同的条件,渲染不同的内容
// react中的条件渲染,和js的if-else是完全一样
function UserGreeting() {
  return <div>欢迎回来,尊贵的v12用户</div>
}

function GuestGreeting() {
  return <div>你好,请先登录</div>
}

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      isLogin: false
    }
  }
  // 完成了条件渲染,根据isLogin来渲染不同的内容
  render() {
    if (this.state.isLogin) {
      return <UserGreeting />
    } else {
      return <GuestGreeting />
    }
  }
}

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

6、React条件渲染-元素变量

class Score extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      score: 90
    }
  }

  render() {
    // 可以使用变量来保存react的对象
    let content = null
    if (this.state.score >= 90) {
      // 元素变量, 把一个react对象赋值给一个变量
      content = <p>A</p>
    } else if (this.state.score >= 80) {
      content = <p>B</p>
    } else if (this.state.score >= 70) {
      content = <p>C</p>
    } else if (this.state.score >= 60) {
      content = <p>D</p>
    } else {
      content = <p>E</p>
    }
    return (
      <div>
        <h3>提示消息</h3>
        <p>你本次的成绩是</p>
        {content}
      </div>
    )
  }
}

ReactDOM.render(<Score />, document.getElementById('app'))

7、React条件渲染-与运算符

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      score: 90,
      age: 18
    }
  }

  render() {
    return (
      <div>
        <h3>提示消息</h3>
        {/* 可以在{}中直接书写任意的js表达式 */}
        {/* {this.state.age >= 18 && <div>成年人</div>}
        {this.state.age < 18 && <div>未成年人</div>} */}
        {this.state.age >= 18 ? <div>成年人</div> : <div>未成年人</div>}
      </div>
    )
  }
}

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

8、React条件渲染-阻止组件渲染

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      age: 18
    }
  }

  render() {
    if (this.state.age < 18) {
      // render一旦return null 就不会渲染其他内容
      return null
    }
    return (
      <div>
        <h3>提示消息</h3>
        <p>以下内容特别劲爆,未成年人不允许观看</p>
      </div>
    )
  }
}

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

// 条件渲染
// 1. 使用if-else根据条件来渲染不同的组件
// 2. 可以使用变量以及if-else来决定组件显示的内容
// 3. &&  三元表达式  return null

// react的条件渲染和js是完全一致的。

9、React列表渲染

class List extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      list: ['张飞', '赵云', '马超', '貂蝉']
    }
  }

  render() {
    let content = this.state.list.map((item, index) => (
      <li key={index}>{item}</li>
    ))
    return (
      <div>
        <h3>人物列表</h3>
        <ul>
          {/* 直接显示了一个数组 */}
          {content}
        </ul>
      </div>
    )
  }
}

ReactDOM.render(<List />, document.getElementById('app'))

// react中无论是条件渲染或者是列表渲染,都在js

10、React列表渲染

class List extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      list: [
        { id: 1, name: 'zs', age: 18, gender: '男' },
        { id: 2, name: 'ls', age: 19, gender: '男' },
        { id: 3, name: 'ww', age: 20, gender: '女' }
      ]
    }
  }
  render() {
    // key只有在兄弟之间才有意义,应该唯一
    let content = this.state.list.map(item => (
      <tr key={item.id}>
        <td>{item.id}</td>
        <td>{item.name}</td>
        <td>{item.age}</td>
      </tr>
    ))
    return (
      <table>
        <tbody>{content}</tbody>
      </table>
    )
  }
}

ReactDOM.render(<List />, document.getElementById('app'))

// react中无论是条件渲染或者是列表渲染,都在js

11、React列表渲染-可以直接在Jsx中使用map

class List extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      list: [
        { id: 1, name: 'zs', age: 18, gender: '男' },
        { id: 2, name: 'ls', age: 19, gender: '男' },
        { id: 3, name: 'ww', age: 20, gender: '女' }
      ]
    }
  }
  render() {
    let content = this.state.list.map(item => (
      <tr key={item.id}>
        <td>{item.id}</td>
        <td>{item.name}</td>
        <td>{item.age}</td>
        <td>{item.gender}</td>
      </tr>
    ))
    return (
      <table>
        <tbody>
          {/* 可以直接在{}中遍历 */}
          {content}
        </tbody>
      </table>
    )
  }
}

ReactDOM.render(<List />, document.getElementById('app'))

// react中无论是条件渲染或者是列表渲染,都在js

12、案例-评论列表

class Comment extends React.Component {
  constructor(props) {
    super(props)

    // 添加状态
    this.state = {
      list: [
        { id: 1, name: '张三', content: '沙发' },
        { id: 2, name: '李四', content: '板凳' },
        { id: 3, name: '王五', content: '卖瓜子' },
        { id: 4, name: '赵六', content: '今天吃了没' }
      ]
    }
  }
  render() {
    return (
      <div>
        <h1>评论案例</h1>
        <ul>
          {this.state.list.map(item => (
            <li key={item.id}>
              <h3>
                评论人:
                {item.name}
              </h3>
              <p>
                评论内容:
                {item.content}
              </p>
            </li>
          ))}
        </ul>
      </div>
    )
  }
}

ReactDOM.render(<Comment />, document.getElementById('app'))

13、案例-评论列表-多组件

// 评论组件
class Comment extends React.Component {
  constructor(props) {
    super(props)

    // 添加状态
    this.state = {
      list: [
        { id: 1, name: '张三', content: '沙发' },
        { id: 2, name: '李四', content: '板凳' },
        { id: 3, name: '王五', content: '卖瓜子' },
        { id: 4, name: '赵六', content: '今天吃了没' }
      ]
    }
  }
  render() {
    return (
      <div>
        <h1>评论案例</h1>
        <ul>
          {this.state.list.map(item => (
            <Item key={item.id} data={item} />
          ))}
        </ul>
      </div>
    )
  }
}

// 评论项组件,没有状态,数据是父组件传递过来的
function Item(props) {
  return (
    <li>
      <h3>
        评论人:
        {props.data.name}
      </h3>
      <p>评论内容 {props.data.content}</p>
    </li>
  )
}

ReactDOM.render(<Comment />, document.getElementById('app'))

14、案例-评论列表-React中如何设置样式

//react中设置样式,有两种方式
// 1. 给元素添加一个className, 设置一个类样式
// 2. 给元素添加一个style属性,通过style属性设置行内样式
// 在使用style给元素设置样式的时候,style={对象}

class Comment extends React.Component {
  constructor(props) {
    super(props)

    // 添加状态
    this.state = {
      list: [
        { id: 1, name: '张三', content: '沙发' },
        { id: 2, name: '李四', content: '板凳' },
        { id: 3, name: '王五', content: '卖瓜子' },
        { id: 4, name: '赵六', content: '今天吃了没' }
      ],
      bgColor: 'pink'
    }
  }
  render() {
    return (
      <div style={{ backgroundColor: this.state.bgColor }}>
        <h1>评论案例</h1>
        <ul style={{ listStyle: 'none' }}>
          {this.state.list.map(item => (
            <Item key={item.id} data={item} />
          ))}
        </ul>
      </div>
    )
  }
}

// 评论项组件,没有状态,数据是父组件传递过来的
function Item(props) {
  let liStyle = { height: 100 }
  return (
    <li style={liStyle}>
      <h3>
        评论人:
        {props.data.name}
      </h3>
      <p>评论内容 {props.data.content}</p>
    </li>
  )
}

ReactDOM.render(<Comment />, document.getElementById('app'))

15、React表单

// react操作表单的元素,操作表单的目的: 获取到用户输入的内容
// react操作表单: 受控组件  非受控组件

// 受控组件: 在当前组件中的表单元素受到了react的控制,
//1. 当表单元素的内容发生改变,react对应的状态也要发生改变
//2. 当react对应的状态发生改变,表单元素的内容也要发生改变。
class Form extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      username: 'hello react'
    }
  }
  render() {
    // 一旦给input设置了value属性,value属性对应了组件中的一个状态,受控组件
    // 表单元素的值受到了react的控制,我们发现,表单没办法输入,没办法改变了
    // 除了指定一个vlaue属性,还需要指定onChange事件,用来处理内容的变化
    return (
      <input
        type="text"
        value={this.state.username}
        onChange={this.handleChange}
      />
    )
  }
  handleChange = e => {
    // 我们需要改变 state.username的值
    this.setState({
      username: e.target.value
    })
  }
}

ReactDOM.render(<Form />, document.getElementById('app'))

16、React表单-受控组件-textarea

class Form extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      username: 'hello react',
      content: '我是内容'
    }
  }
  render() {
    return (
      <div>
        <h3>input</h3>
        <input
          type="text"
          value={this.state.username}
          onChange={this.handleChange}
        />
        <h3>textarea</h3>
        <textarea
          cols="30"
          rows="10"
          value={this.state.content}
          onChange={this.handleContent}
        />
      </div>
    )
  }
  handleChange = e => {
    // 我们需要改变 state.username的值
    this.setState({
      username: e.target.value
    })
  }
  handleContent = e => {
    // 获取到文本框的内容
    this.setState({
      content: e.target.value
    })
  }
}

ReactDOM.render(<Form />, document.getElementById('app'))

17、React表单-受控组件-select

class Form extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      username: 'hello react',
      content: '我是内容',
      city: 4
    }
  }
  render() {
    return (
      <div>
        <h3>input</h3>
        <input
          type="text"
          value={this.state.username}
          onChange={this.handleChange}
        />
        <h3>textarea</h3>
        <textarea
          cols="30"
          rows="10"
          value={this.state.content}
          onChange={this.handleContent}
        />
        <h3>select</h3>
        <select value={this.state.city} onChange={this.handleSelect}>
          <option value="1">北京</option>
          <option value="2">上海</option>
          <option value="3">广州</option>
          <option value="4">深圳</option>
        </select>
      </div>
    )
  }
  handleChange = e => {
    // 我们需要改变 state.username的值
    this.setState({
      username: e.target.value
    })
  }
  handleContent = e => {
    // 获取到文本框的内容
    this.setState({
      content: e.target.value
    })
  }
  handleSelect = e => {
    this.setState({
      city: e.target.value
    })
  }
}

ReactDOM.render(<Form />, document.getElementById('app'))

18、React表单-受控组件-通用的处理程序

class Form extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      username: 'hello react',
      content: '我是内容',
      city: 4
    }
  }
  render() {
    return (
      <div>
        <h3>input</h3>
        <input
          type="text"
          value={this.state.username}
          onChange={this.handleChange}
          name="username"
        />
        <h3>textarea</h3>
        <textarea
          cols="30"
          rows="10"
          value={this.state.content}
          onChange={this.handleChange}
          name="content"
        />
        <h3>select</h3>
        <select
          value={this.state.city}
          onChange={this.handleChange}
          name="city"
        >
          <option value="1">北京</option>
          <option value="2">上海</option>
          <option value="3">广州</option>
          <option value="4">深圳</option>
        </select>
      </div>
    )
  }
  handleChange = e => {
    let name = e.target.name
    // 我们需要改变 state.username的值
    // es6的属性名表达式
    this.state[name] = e.target.value
    this.setState(this.state)
  }
}

ReactDOM.render(<Form />, document.getElementById('app'))

19、React非受控组件

// 1. 在构造函数中,需要自己创建一个引用  ref

class Form extends React.Component {
  constructor(props) {
    super(props)

    // 1. 创建ref
    this.usernameRef = React.createRef()
    this.buttonRef = React.createRef()
  }
  render() {
    return (
      <div>
        {/* 2. 我们创建的ref可以 在组件的任意地方使用 */}
        <input ref={this.usernameRef} type="text" />
        <button ref={this.buttonRef} onClick={this.get}>
          获取value值
        </button>
      </div>
    )
  }
  get = () => {
    // 获取input框的value值
    // 受控组件: 我们把input框的value值交给react来处理
    // 非受控组件: 我们需要手动的操作DOM,手动获取到DOM的value值
    // refs: 用于操作DOM的

    // 3. 通过this.usernameRef.current
    console.log(this.usernameRef.current.value)
  }
}

ReactDOM.render(<Form />, document.getElementById('app'))

20、图书管理案例-列表

class Book extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      list: [
        { id: 1, name: '红楼梦', desc: '一堆乱七八糟的破事' },
        { id: 2, name: '西游记', desc: '小时候的经典' },
        { id: 3, name: '权威指南', desc: 'js程序员必读' }
      ],
      name: '',
      desc: '',
      id: '',
      index: 3
    }
  }
  render() {
    return (
      <div className="container">
        <div className="form">
          书名:
          <input
            type="text"
            value={this.state.name}
            onChange={this.handleChange}
            name="name"
          />
          描述:
          <input
            type="text"
            value={this.state.desc}
            onChange={this.handleChange}
            name="desc"
          />
          <button onClick={this.addBook}>添加</button>
        </div>
        <table>
          <thead>
            <tr>
              <th>编号</th>
              <th>书名</th>
              <th>描述</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            {this.state.list.map((item, index) => (
              <tr key={item.id}>
                <td>{index + 1}</td>
                <td>{item.name}</td>
                <td>{item.desc}</td>
                <td>
                  <a href="#" onClick={this.delBook.bind(this, item.id)}>
                    删除
                  </a>
                  |
                  <a href="#" onClick={this.showEdit.bind(this, item)}>
                    修改
                  </a>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    )
  }

  addBook = () => {
    // 判断是否有id值,如果有,是修改,否则是添加
    if (this.state.id) {
      // 修改
      // 根据id找到需要修改的下标
      let idx = this.state.list.findIndex(item => item.id === this.state.id)
      this.state.list[idx].name = this.state.name
      this.state.list[idx].desc = this.state.desc
    } else {
      // 添加
      // 添加图书
      this.state.list.push({
        id: ++this.state.index,
        name: this.state.name,
        desc: this.state.desc
      })
    }
    // 清空name和desc
    this.state.name = ''
    this.state.desc = ''
    this.state.id = ''
    this.setState(this.state)
  }
  handleChange = e => {
    let { name, value } = e.target
    this.setState({
      [name]: value
    })
  }
  delBook(id, e) {
    e.preventDefault()
    // 删除需要id
    // 根据id获取到下标
    let idx = this.state.list.findIndex(item => item.id === id)
    // 删除对应的数据
    this.state.list.splice(idx, 1)
    this.setState(this.state)
  }
  showEdit = (book, e) => {
    e.preventDefault()
    this.state.id = book.id
    this.state.name = book.name
    this.state.desc = book.desc
    this.setState(this.state)
  }
}

ReactDOM.render(<Book />, document.getElementById('app'))

(1)index.css

/* * {
  margin: 0;
  padding: 0;
}
.container {
  background-color: pink;
}

.item {
  border: 1px solid #000;
  height: 100px;
} */

.container {
  width: 600px;
}

table {
  margin-top: 30px;
  border: 1px solid blue;
  border-collapse: collapse;
  width: 100%;
}

table th,
table td {
  border: 1px solid blue;
  height: 50px;
  line-height: 50px;
  text-align: center;
}

(2)index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <link rel="stylesheet" href="index.css">
</head>

<body>
  <div id="app"></div>

  <!-- 1. 引包 -->
  <script src="lib/react.development.js"></script>
  <script src="lib/react-dom.development.js"></script>
  <script src="lib/babel.min.js"></script>
  <!-- 如果想要引入一个外部的文件,不能使用file协议, http协议 -->
  <!-- <script type="text/babel" src="01-react复习.js"></script> -->
  <!-- <script type="text/babel" src="02-react事件.js"></script> -->
  <!-- <script type="text/babel" src="03-react事件-this的问题.js"></script> -->
  <!-- <script type="text/babel" src="04-react事件-传参的问题.js"></script> -->
  <!-- <script type="text/babel" src="05-react条件渲染.js"></script> -->
  <!-- <script type="text/babel" src="06-react条件渲染-元素变量.js"></script> -->
  <!-- <script type="text/babel" src="07-react条件渲染-与运算符.js"></script> -->
  <!-- <script type="text/babel" src="08-react条件渲染-阻止组件渲染.js"></script> -->
  <!-- <script type="text/babel" src="11-react列表渲染-可以直接在jsx中使用map.js"></script> -->
  <!-- <script type="text/babel" src="12-案例-评论列表.js"></script> -->
  <!-- <script type="text/babel" src="13-案例-评论列表-多组件.js"></script> -->
  <!-- <script type="text/babel" src="14-案例-评论列表-react中如何设置样式.js"></script> -->
  <!-- <script type="text/babel" src="15-react表单.js"></script> -->
  <!-- <script type="text/babel" src="16-react表单-受控组件-textarea.js"></script> -->
  <!-- <script type="text/babel" src="17-react表单-受控组件-select.js"></script> -->
  <!-- <script type="text/babel" src="19-react非受控组件.js"></script> -->
  <script type="text/babel" src="20-图书管理案例-列表.js"></script>
</body>

</html>
发布了285 篇原创文章 · 获赞 45 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/qq_31784189/article/details/103330527