React【事件对象、组件关系(组件的props、子组件向父组件传递数据 )、组件组合(组件状态State、State的更新、setState重新渲染组件跟子组件、基于props初始化)】(二)

文章目录

事件对象

事件处理程序传递参数

函数组件与 class 组件

组件关系

组件的props

子组件向父组件传递数据 

组件组合

组件状态State

State的更新

setState重新渲染组件跟子组件

基于props初始化state


事件对象

默认情况下,react会传递一个事件对象到事件的处理函数,这个事件对象是一个合成事件对象。 

const onAdd=(e)=>{console.log(e)}
return <button onClick={onAdd }>点击</button>

 使用事件对象阻止默认事件、阻止冒泡。

const onAdd=(e)=>{
  e.preventDefault();//阻止默认事件
  e.stopPropagation()//阻止事件冒泡
  console.log(e);
}
 return <div onClick={()=>{console.log('div的点击事件被触发')}}>
  <a onClick={onAdd } href="#">点击</a> 
 </div>

通过事件对象获取输入的值。

return <input onChange={(e)=> {console.log(e.target.value)}}/>

事件处理程序传递参数

const onAdd = (param) => {
  return (e)=>{
     console.log(param)
     console.log(e)
   }
 }
 return <button onClick={onAdd('hello')}>点击</button>

 或者

const onAdd = (param, e) => {
  console.log(param)
  console.log(e)
}
 return <button onClick={(e) => onAdd('hello', e)}>点击</button>

函数组件与 class 组件

函数组件
可以使用首字母为大写的名称定义一个函数,并且让这个函数返回一个 React 元素。
这类组件被称为“函数组件”。 

function Home() {
  return <h1>Hello, txc</h1>
}

类组件
可以使用ES6 的 class来定义组件,通过定义render函数来返回react元素。

class Home extends React.Component {
 render() {
   return <h1>Hello, txc</h1>;
 }
}

渲染组件
使用组件,直接像使用普通标签那样使用就可以了。

<App/> 

class组件中的事件处理

类组件中的 this 指向类的实例,在render函数中可以通过 this 访问该类的实例的属性。 

class App extends React.Component{
 onAdd(){
  console.log('点击事件发生了')
}
 render(){
  return <div>
   <button onClick={this.onAdd}>点击</button>
  </div>
  }
}

提示:
在 JavaScript 中,class 的方法默认不会绑定 this

class App extends React.Component {
 onSum(num1,num2){
  return num1+num2
}
 onAdd() {
   //直接在函数内访问this,是访问不到的,为Undefined
  console.log(this)
  this.onSum(1,2)
}
 render() {
  return <div>
      <button onClick={this.onAdd}>点击</button>
      </div>
   }
}

 手动绑定函数中 this 的指向

1、方法一:在render函数中绑定

class App extends React.Component {
 onSum(num1,num2){
  return num1+num2
}
 onAdd() {
   //直接在函数内访问this,是访问不到的
  console.log(this)
  console.log(this.onSum(1,2))
}
 render() {
  return <div>
   <button onClick=  {this.onAdd.bind(this)}>点击</button>
  </div>
   }
}

方法二:在类的构造函数中绑定

class App extends React.Component {
 constructor(){ 
  super()
   //因为在类的构造函数中也可以访问this
  this.onAdd=this.onAdd.bind(this)
}
 onSum(num1,num2){
  return num1+num2
}
 onAdd() {
  console.log(this)
 console.log(this.onSum(1,2))
}
 render() {
  console.log(this)
  return <div>
   <button onClick={this.onAdd}>点击</button>
  </div>
   }
}

方法三:使用箭头函数

class App extends React.Component {
 onSum(num1,num2){
  return num1+num2
}
 onAdd=()=> {
  console.log(this)
 console.log(this.onSum(1,2))
}
 render() {
  console.log(this)
  return <div>
   <button onClick={this.onAdd}>点击</button>
  </div>
   }
}

组件关系

App.js 

function App() {//App组件是Home组件跟Welcome的子组件
  return <div>
      <Home/>
      <Welcome/>
    </div>
}

引用其它组件的组件叫做父组件,被引用在其它组件界面的组件叫做子组件

组件的props

组件与组件之间是可以交互的,可以互相传递数据的。

我们可以通过 props 属性让父组件向子组件传递数据。 

1、函数的组件的props

return (
    <div>
      <Child title="xiaotong"/>
    </div>
)
export default function Child(props) {
 return (
  <div>
    <h3>欢迎欢迎~ 热烈欢迎!</h3>
    <p>{ props.title }</p>
  </div>
)}

2、class的组件的props

render() {
  const info={title:'首页',desc:'这里是网站的首页,也是默认启动页面'}
  return (
    <div>
      <Child info={info}/>
    </div>
 )
}
import React from 'react'

export default class Child extends
React.Component {
 render() {
   const {title,desc}=this.props.info
  return <div>
     <h3>{ title }</h3>
     <p>{ desc }</p>
   </div>
  }
}

提示:
组件可以接受任意 props,包括基本数据类型,React 元素以及函数。

提示:
组件无论是使用函数声明还是通过 class 声明,都决不能修改自身的 props,props具有只读性。 

子组件向父组件传递数据 

子组件向父组件传递数据,依然可以利用props实现。
props对于数据类型没有限制,那么就可以利用props传递函数,然后在子组件中调用传递进来的函数,并且在调用的时候传递数据。 

// Parent.js
import React, { Component } from 'react'
import Child from "./Child"

export default class Parent extends
Component {
  onChange=(data){
    console.log(data)
 }
  render() {
    return (
      <div>
        <h3>Parent</h3>
        <Child onChange={ this.onChange }/>
      </div>
   )
 }
}
// Child.js
import React, { Component } from 'react'

export default class Child extends Component
{
 
  onChange=(e)=>{
  
 this.props.onChange&&this.props.onChange(e.target.value)
 }
  render() {
    return (
      <div>
        <h3>Child</h3>
        <input onChange={ this.onChange }/>
      </div>
   )
 }
}

组件组合

组件当中也是可以嵌套其它元素或者组件的。

<Home>
  <div>一些要放在home组件当中的内容</div>
  <p>xxxxxx</p>
</Home>

 通过 props.children 获取组件内部嵌套的内容。

function Home (props){
  return <div>
    <h3>这是home页面</h3>
    {/* 最红props.children会被替换为嵌套的内容 */}
   {props.children}
  </div>
}

提示:
组合也同样适用于以 class 形式定义的组件。

组件状态State

State 与 props 类似,但是 state 是组件私有的,并且完全受控于所属的组件。
使用 State的目的 :管理组件内部状态,并且当组件内部状态发生变化的时候,重新渲染页面。

 1、初始化并使用state

    1.1、在类的构造函数中为 state 赋初值,并且通过 this.state 访问数据。

import React from 'react'
export default class StateTest extends React.Component {
 constructor() {
      super();
      this.state = {date: new Date()};
}
 render() {
  return <p>{ this.state.date }</p>
  }
}

2、使用 this.setState() 更新state并让页面重新渲染

import React from 'react'

export default class StateTest extends
React.Component {
  constructor() {
    super();
    this.state = { date: new Date() };
 }
  onChange = () => {
    this.setState({ date: new Date()
})
 }
  render() {
    return <div>
      <p> {this.state.date.toLocaleTimeString()}</p>
      <button onClick= {this.onChange}>更新state</button>
    </div>
 }
}

提示
一般我们只在类组件里面使用 state ,函数组件当中不使用 state ,所以有的时候把类组件叫做有状态组件,函数组件叫 做无状态组件。

思考:State与Props的区别
State:负责组件内部的状态管理
Props:负责组件与组件之间的数据交互 

State的更新

 1、更改state,不要直接修改 state

this.state.date=new Date()
//这样的代码是不会生效的

提示:
只有使用setState页面才会重新渲染。

2、使用 setState 去更新state
    2.1、setState 是异步的 

this.setState({ date: new Date() })
//上面setState之后,下面的代码是没法获取到更新后的state的
console.log(this.state.date.toLocaleTimeString())

解决方案,直接给setState传递回调函数。

this.setState({ date: new Date() }, (state)=>{
    console.log(state.date.toLocaleTimeString())
  })

或者

this.setState({ date: new Date() })
this.setState((state)=>{
    console.log(state.date.toLocaleTimeString())
   })

3、setState 会合并state

当你调用 setState() 的时候,React 会把你提供的对象合并到当前的 state。

constructor() {
  super();
  this.state = { date: new Date(),title:'今天的天气真不错' };
}
onChange = () => {
  this.setState({ date: new Date() })
  //在这里直接设置为{date:new Date},则与原来的{date:new Date,title:'今天的天气很不错合并'},不会直接干掉title属性,只会替换date属性的值
}

setState重新渲染组件跟子组件

1、调用setState,组件的render方法会被重新调用,从而重新渲染页面 

onChange = () => {
    this.setState({ date: new Date()
})
  
 }
  render() {
    return <div>
      <p> {this.state.date.toLocaleTimeString()}</p>
      <button onClick= {this.onChange}>更新state</button>
    </div>
 }

2、调用setState,子组件也会被重新渲染

//StateTest.js
import React from 'react'
import StateTestChild from './StateTestChild';
export default class StateTest extends  React.Component {
  constructor() {
    super();
    this.state = { date: new  Date(),title:'今天的天气真不错' };
 }
  onChange = () => {
    this.setState({ date: new Date()
 })
 }
  render() {
    return <div>
      <p> {this.state.date.toLocaleTimeString()}</p>
      <button onClick= {this.onChange}>更新state</button>
      <StateTestChild  date= {this.state.date.toLocaleTimeString()}/>
    </div>
 }
}
//StateTestChild.js
export default function StateTestChild(props){
  return <div>
    <h3>我是子组件</h3>
   子组件的时间:{props.date}
  </div>
}

基于props初始化state

//StateTestChild.js
export default class StateTestChild extends
React.Component{
  constructor(props){
    //如果不给super传入props,则在constructor中没法使用this.props
    super(props)
    //使用Props传过来的数据,初始化state
    this.state={desc:'现在的时间是'+props.date}
 }
  render(){
    return <div>
    <h3>我是子组件</h3>
   {/* 这里直接使用state状态 */}
   子组件的时间:{this.state.desc}
  </div>
 }
}

 提示:
构造函数当中的参数可以获取props。
class 组件应该始终使用 props 参数来调用父类的构造函数。

猜你喜欢

转载自blog.csdn.net/m0_58719994/article/details/132570660