02-React受控组件及非受控组件、数据渲染、事件处理、组件通信

一、受控组件和非受控组件

React组件的数据渲染是否被调用 是通过 传递过来的props完全控制
控制则为受控组件,否则非受控组件。


二、数据渲染

1、条件渲染
{ flag ? "开启" : "关闭" }

2、列表渲染
渲染的元素必须用key属性做唯一标识

const people = [{
	  id: 1,
	  name: 'Leo',
	  age: 35
}, {
	  id: 2,
	  name: 'XiaoMing',
	  age: 16
}]
// 渲染列表
{
  people.map(person => {
    return (
      <dl key={person.id}>
        <dt>{person.name}</dt>
        <dd>age: {person.age}</dd>
      </dl>
    )
  })
}

使用dangerouslySetHTML属性,它允许我们动态设置innerHTML
<div dangerouslySetInnerHTML={{__html: this.state.content}} />


三、事件处理

1、React的事件并不是原生事件,而是合成事件。所以命名使用驼峰命名法,如onClick。

2、事件handle的写法

  • 直接在render里写行内的箭头函数(不推荐)
  • 在组件内使用箭头函数定义一个方法(推荐)
  • 直接在组件内定义一个非箭头函数的方法,然后在render里直接使用onClick={this.handleClick.bind(this)}(不推荐)
  • 直接在组件内定义一个非箭头函数的方法,然后在constructor里bind(this)(推荐)

注意: 事件不能定义在函数式

3、event对象
React中的event对象并不是浏览器提供的,而是它自己内部所构建的。
它同样具有event.stopPropagationevent.preventDefault 这种常用的方法

事件对象中的值很多都是null,但是可以正常使用

4、事件的参数传递

  • 在render里调用方法的地方外面包一层箭头函数
  • 在render里通过this.handleEvent.bind(this, 参数)这样的方式来传递
  • 通过event传递
  • 比较推荐的是做一个子组件, 在父组件中定义方法,通过props传递到子组件中,然后在子组件件通过this.props.method来调用
    //处理用户输入
    import React, { Component } from 'react'
    import ReactDOM from 'react-dom'
    
    class App extends Component {
      constructor() {
        super()
        this.state = {
          xing: '',
          ming: ''
        }
      }
      handleInputChange = (e) => {
        this.setState({
          [e.target.name]: e.target.value
        })
      }
      render () {
        const {
          xing,
          ming
        } = this.state
        return (
      		<div>
            <label>
              <span>:</span>
              <input
                type="text"
                name="xing"
                value={xing}
                onChange={this.handleInputChange}
              />
            </label>
            <label>
              <span>:</span>
              <input
                type="text"
                name="ming"
                value={ming}
                onChange={this.handleInputChange}
              />
            </label>
            <p>欢迎您: {xing}{ming}</p>
          </div>
      	)
      }
    }
    ReactDOM.render(
    	<App/>,
      document.getElementById('root')
    )
    
  • ref绑定:
    普通绑定
    <input type="text" ref = "user"/>
    函数形式
    <input type="text" ref = { el => this.user = el }/>

四、组件通信

1、父子组件通信
无论父组件传递是props还是state,子组件都是通过props接收

2、子父组件通信
父组件传递方法给子组件,子组件调用父组件传递过来的方法
​ 注意: 自己的状态自己更改

3、非父子组件通信
​ref = ‘xxx’                               this.refs.xxx
ref = { el => this.xxx = el }       this.xxx 【 推荐

4、跨组件通信

  • 创建上下文 React.createContext()
  • 使用上下文包裹目标组件的父组件
 <MoneyContext.Provider value = { money }>
    	<Father></Father>
 </MoneyContext.Provider>
  • 在目标组件中先定义一个静态属性 static contextType = MoneyContext
  • 通过 this.context来使用数据
// counterContext.js
import React, { Component, createContext } from 'react'

const {
  Provider,
  Consumer: CountConsumer
} = createContext()

class CountProvider extends Component {
  constructor () {
    super()
    this.state = {
      count: 1
    }
  }
  increaseCount = () => {
    this.setState({
      count: this.state.count + 1
    })
  }
  decreaseCount = () => {
    this.setState({
      count: this.state.count - 1
    })
  }
  render() {
    return (
      <Provider value={{
        count: this.state.count,
        increaseCount: this.increaseCount,
        decreaseCount: this.decreaseCount
      }}
      >
        {this.props.children}
      </Provider>
    )
  }
}

export {
  CountProvider,
  CountConsumer
}
// 定义CountButton组件
const CountButton = (props) => {
  return (
    <CountConsumer>
      // consumer的children必须是一个方法
      {
        ({ increaseCount, decreaseCount }) => {
          const { type } = props
          const handleClick = type === 'increase' ? increaseCount : decreaseCount
          const btnText = type === 'increase' ? '+' : '-'
          return <button onClick={handleClick}>{btnText}</button>
        }
      }
    </CountConsumer>
  )
}
// 定义count组件,用于显示数量
const Count = (prop) => {
  return (
    <CountConsumer>
      {
        ({ count }) => {
          return <span>{count}</span>
        }
      }
    </CountConsumer>
  )
}
// 组合
class App extends Component {
  render () {
    return (
  		<CountProvider>
        <CountButton type='decrease' />
        <Count />
        <CountButton type='increase' />
      </CountProvider>
  	)
  }
}

5、多组件状态共享

  • Flux
  • redux
  • mobx 【 阿里 】
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值