React-组件&Props

组件

函数组件

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

"函数组件"本质上就是 JavaScript 函数

class组件

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

渲染组件

当 React 元素为用户自定义组件时,它会将 JSX 所接收的属性(attributes)以及子组件(children)转换为单个对象传递给组件,这个对象被称之为 “props”。

例如,这段代码会在页面上渲染 “Hello, Sara”:

function Welcome(props) {  
  return <h1>Hello, {props.name}</h1>;
}

const root = ReactDOM.createRoot(document.getElementById('root'));
const element = <Welcome name="Sara" />;
root.render(element);

回顾一下这个例子中发生了什么:

  • 调用root.render()函数,并传入 <Welcome name="Sara" /> 作为参数。
  • React 调用 Welcome 组件,并将 {name: 'Sara'} 作为props传入。
  • Welcome 组件将 <h1>Hello, Sara</h1> 元素作为返回值。
  • React DOM 将 DOM 高效地更新为 <h1>Hello, Sara</h1>

注意: 组件名称必须以大写字母开头!!!
React 会将以小写字母开头的组件视为原生 DOM 标签。例如,<div /> 代表 HTML 的 div 标签,而 <Welcome /> 则代表一个组件,并且需在作用域内使用 Welcome

组合组件

组件可以在其输出中引用其他组件

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

function App() {
  return (
    <div>
      <Welcome name="Sara" />      
      <Welcome name="Cahal" />      
      <Welcome name="Edite" />    
    </div>
  );
}

提取组件

将组件拆分为更小的组件。

参考如下Comment组件:

function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <img className="Avatar"
          src={props.author.avatarUrl}
          alt={props.author.name}
        />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

该组件由于嵌套的关系,变得难以维护,且很难复用它的各个部分。因此,让我们从中提取一些组件出来。

首先,我们将提取 Avatar 组件:

function Avatar(props) {
    return (
        <img className="Avatar"   
            src={props.user.avatarUrl}     
            alt={props.user.name}    
        /> 
    );
}

Avatar 不需知道它在 Comment 组件内部是如何渲染的。因此,我们给它的 props 起了一个更通用的名字:user,而不是 author

我们建议从组件自身的角度命名 props,而不是依赖于调用组件的上下文命名。

我们现在针对 Comment 做些微小调整:

function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <Avatar user={props.author} />      
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

接下来,将提取 UserInfo 组件,该组件在用户名旁渲染 Avatar 组件:

function UserInfo(props) {
  return (
    <div className="UserInfo">
        <Avatar user={props.user} />
        <div className="UserInfo-name">
            {props.user.name} 
        </div>   
    </div>  );
}

进一步简化 Comment 组件:

function Comment(props) {
  return (
    <div className="Comment">
      <UserInfo user={props.author} />      
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

小总结:提取组件可能繁重,但值得

Props 的只读性

组件无论是使用函数声明还是通过 class 声明,都绝不能修改自身的 props

React 非常灵活,但它也有一个严格的规则:

所有 React 组件都必须像纯函数一样保护它们的 props 不被更改

组件通讯

父组件传递数据给子组件

  • 1.父组件提供要传递的state数据
  • 2.给子组件标签添加属性,值为state中的数据
  • 3.子组件中通过props接收父组件中传递的数据
class Parent extends React.Component{
    state ={lastName:'王'}
    render(){
        return(
        <div>
        传递数据给子组件:<Child name={this.state.lastName}/>
        </div>
        )
    }
}

function Child(props){
    return<div>子组件接收到数据:{props.name}</div>
}

子组件传递数据给父组件

思路:利用回调函数,父组件提供回调,子组件调用,将要传递的数据作为回调函数的参数。

  • 1.父组件提供一个回调函数(用于接收数据)
  • 2.将该函数作为属性的值,传递给子组件
class Parent extends React.Component{
    getchildMsg = (msg)=>{
        console.log('接收到子组件数据',msg)
    }
    render(){   
        return(
            <div>
                子组件:<Child getMsg={this.getchildMsg}/>
            </div>
        )
    }
}
  • 3.子组件通过props调用回调函数
class Child extends React.Component{
    state ={childMsg:'React'}
    handleClick =()=>{
        this.props.getMsg(this.state.childMsg)
    }
    render(){   
        return(
            <button onClick={this.handleClick}>点我,给父组件传递数据</button>
        )
    }
}

兄弟组件

  • 将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态
  • 思想:状态提升
  • 公共父组件职责:
    • 1.提供共享状态
    • 2.提供操作共享状态的方法
  • 要通讯的子组件只需通过pops接收状态或操作状态的方法
class Counter extends React.Component{
    //提供共享状态
    state={
        count:0
    }
    //提供修改状态的方法
    onIncrement =()=>{
        this.setstate({
            count:this.state.count + 1
        })
    }
    render(){
        return(
        <div>
            <Child1 count={this.state.count} />
            <Child2 onIncrement={this.onIncrement} />
        </div>
        )
    }
}

const child1=props =>{
    return<h1>计数器:{props.count}</h1>
}
const child2=props =>{
    return <button onClick={()=>props.onIncrement()}>+1</button>
}
posted @ 2022-08-10 22:03  lanercifang  阅读(27)  评论(0)    收藏  举报