React学习02

利用React实现选项卡切换

import React, { Component } from 'react'
import './index.css'
import Center from './components/Center'
import Film from './components/Film'
import Cinema from './components/Cinema'

// App 根组件
export default class App extends Component {
  state = {
    list: [
      { id: 1, text: '电影' },
      { id: 2, text: '影院' },
      { id: 3, text: '我的' },
    ],
    curIndex: 0
  }
  handleClick = (index) => {
    this.setState({
      curIndex: index
    })
  }
  getWhichComponent () {
    switch (this.state.curIndex) {
      case 0:
        return <Film></Film>
      case 1:
        return <Cinema></Cinema>
      case 2:
        return <Center></Center>
      default:
        return null
    }
  }
  render () {
    return (
      <div>
        {this.getWhichComponent()}
        <ul>
          {this.state.list.map((item, index) =>
            <li key={item.id} className={this.state.curIndex === index ? 'active' : null}
              onClick={() => this.handleClick(index)}>
              {item.text}</li>)}
        </ul>
      </div>
    )
  }
}

练习案例:获取影院数据并渲染列表、模糊搜索

import React, { Component } from 'react'
import axios from 'axios'
export default class Cinema extends Component {
  state = {
    cinemaList: [],
    inputVal: '',
    newList: []
  }
  handleInputChange = (e) => {
    this.setState({
      newList: this.state.cinemaList.filter
      (item => item.name.toUpperCase().includes(e.target.value.toUpperCase()))})
    console.log(this.state.newList)
  }
  componentDidMount () {
    // axios请求数据
    axios({
      url: 'https://m.maizuo.com/gateway?cityId=310100&ticketFlag=1&k=8344830',
      headers: {
        'X-Client-Info': '{"a":"3000","ch":"1002","v":"5.2.1","e":"16902932642546383030583297","bc":"310100"}',
        'X-Host': 'mall.film-ticket.cinema.list'
      }
    }).then(res => {
      this.setState({
        cinemaList: res.data.data.cinemas
      })
    }).catch(err => {
      console.log(err)
    })
  }
  render () {
    return (
      <div>
          <input type="text" onChange={(e) => this.handleInputChange(e)}/>
          {this.state.newList.map(item => 
          <dl key={item.cinemaId}>
            <dt>{item.name}</dt>
            <dd>{item.address}</dd>
          </dl>)}
       
      </div>
    )
  }
}

状态的细节

import React, { Component } from 'react'

export default class App extends Component {
  state = {
    count: 0
  }
  handleAdd = () => {
    this.setState({
      count: this.state.count + 1
    }, () => console.log(this.state.count))
  }
  render () {
    return (
      <div>
        <h2>{this.state.count}</h2>
        <button onClick={() => this.handleAdd()}>+1</button>
      </div>
    )
  }
}

React 中的 setState 是一个异步的过程,也就是说在异步状态下,setState 并不是同步执行的。在 React 中,每次调用 setState 都会将新的 state 合并到当前的 state 中,并触发组件的重新渲染。但是,由于 setState 是异步的,React 会将多个 setState 调用合并成一个调用,以提高性能。因此,连续调用多个 setState 时,并不能保证它们按照调用的顺序立即执行,也不能保证前一个 setState 完成后立即执行下一个 setState。为了解决这个问题,React 提供了一个 setState 的第二个参数,可以传递一个回调函数,这个回调函数会在 setState 完成后执行。需要注意的是,在一些特殊情况下,例如在生命周期函数中调用 setState,React 会同步执行 setState,但这并不是 setState 的正常行为。因此,在开发中应该始终将 setState 视为异步执行的过程,以保证代码的正确性。

连续调用 setState 是不会重复执行的。由于 setState 是一个异步操作,React 会将多个 setState 合并成一个调用,以提高性能。React 会根据内部算法决定何时合并 setState 调用,因此在连续调用 setState 时,React 可能会将它们合并成一个调用。如果连续调用 setState 的状态变化是相同的,则只会触发一次重新渲染,从而提高了性能。例如:

this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});

在上面的代码中,两个 setState 调用中的状态变化是相同的,React 只会触发一次重新渲染。

但是,如果连续调用 setState 的状态变化是不同的,则会触发多次重新渲染。例如:

this.setState({count: this.state.count + 1}); 
this.setState({count: this.state.count + 2});

在上面的代码中,两个 setState 调用中的状态变化是不同的,React 会触发两次重新渲染。

需要注意的是,如果在 setState 中依赖于前一个状态的值进行计算,应该使用函数形式的 setState,例如:

this.setState(prevState => ({ count: prevState.count + 1 }));

这样可以确保获取到的 prevState 始终是最新的,从而避免出现意外结果。

受控组件实现列表过滤

import React, { Component } from 'react'

export default class App extends Component {
  state = {
    inputValue: '',
    list: [
      {id: 1, song: '真的爱你'},
      {id: 2, song: '你是我的'},
      {id: 3, song: '一个人'},
      {id: 4, song: '大海'},
      {id: 5, song: '大大小小'},
      {id: 6, song: '上海'},
      {id: 7, song: '牛马'},
      {id: 8, song: '66爱爱'},
    ]
  }
  getRenderList = () => {
    return this.state.list.filter(item => item.song.includes(this.state.inputValue))
  }

  render () {
    return (
      <div>
        <input type="text" value={this.state.inputValue} onChange={(e) => {
          this.setState({inputValue: e.target.value})
        }}/>
        <ul>
          {this.getRenderList().map(item => <li key={item.id}>{item.song}</li>)}
        </ul>
      </div>
    )
  }
}

父子组件之间的通信方式

为了提高组件复用性、灵活性,因此需要父子组件之间的通信。

利用子传父实现抽屉drawer

import React, { Component } from 'react'
// SideBar
class SideBar extends Component {
  render () {
    return (
      <div style={{ backgroundColor: 'skyblue', width: 200 }}>
        <ul>
          <li>1</li>
          <li>2</li>
          <li>3</li>
          <li>4</li>
          <li>5</li>
          <li>5</li>
          <li>5</li>
          <li>5</li>
          <li>5</li>
        </ul>
      </div>
    )
  }
}
// NavBar
class NavBar extends Component {
  handleClick = () => {
    this.props.onValueChange()
  }
  render () {
    return (
      <div style={{ backgroundColor: 'orange' }}>
        <div>NavBar</div>
        <div><button onClick={() => this.handleClick()}>open</button></div>
      </div>
    )
  }
}
class App extends Component {
  state = {
    isShow: true
  }
  onValueChange = () => {
    this.setState({
      isShow: !this.state.isShow
    })
  }
  render () {
    return (
      <div>
        <NavBar onValueChange={this.onValueChange}/>
        {this.state.isShow && <SideBar />}
      </div>
    )
  }
}

export default App

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值