组件通信

5 min

React 组件通信

组件

dom 组件 react支持的 htmlsvg 标签

props

什么是 props html 属性的功能

dom 属性

类名 className

样式

style={
    {
    width:'100vh',
    height:100,
    backgroundColor:'grey'
    //带 - 的写成驼峰
}
}

也可以书写变量

const imgStyle={
    width:'100vh',
    height:100,
    backgroundColor:'grey'
}
return(
    <div>
        <img style={imgStyle}/>
    </div>)

jsx 展开语法

把所有属性书写为一个变量

import image from './logo.svg'
const imgData={
    className='small',
    style:{
    width:'100vh',
    height:100,
    backgroundColor:'grey'
}    }
return(
    <div>
        <img
            //src 标签不能提出
            src={image}
            {...imgData}
            />
    </div>
)

自定义组件 react 的 props

function Artcile() {
  return (
    <div>
      <h2>111</h2>
      <p>222</p>
    </div>
  )
}
export default function App() {
  return (
    <>
      <Article />
      <Article />
      <Article />
      <Article />
    </>

  )
}

如果对组件的结构逻辑 样式复用

内容不复用的话 可以写成

对组件内容定制

步骤

1.对父元素 (上面的 App) 进行请求 请求功能所需要的数据

2.创建组件

3.把数据传给组件

父组件向子组件传普通值

function Detail() {
  return (
    <>
      <p>{content}</p>
      <p>
        状态:
        {active ? '显示' : '隐藏'}
      </p>
    </>
  )
}
function Artcile({ acticleData })
// 采用解构
{
  return (
    <div>
      <h2>{title}</h2>
      <Detail {...articleData}></Detail>
    </div>
  )
  // 此时 Article 没用到 content 和 active
  // 但是 Detail 用到了 可以在 Article 先不传 直接传给 Detail
}
export default function App() {
  const articleData = {
function Detail() {
  return (
    <>
      <p>{content}</p>
      <p>
        状态:
        {active ? '显示' : '隐藏'}
      </p>
    </>
  )
}
function Artcile({ acticleData })
// 采用解构
{
  return (
    <div>
      <h2>{title}</h2>
      <Detail {...articleData}></Detail>
    </div>
  )
  // 此时 Article 没用到 content 和 active
  // 但是 Detail 用到了 可以在 Article 先不传 直接传给 Detail
}
export default function App() {
  const articleData = {
    title: '1',
    detailData: {
      content: '1',
      active: true
    }
  }
  return (
    <>
      <Article
        {...acticleData}
      />
      <Article
        title="2"
        content="2"
        active
      />
      <Article
        title="3"
        content="3"
        active
      />
    </>

  )
}

父组件向子组件传 jsx

插槽 jsx作为 props 传给子组件

function List({ children, title, footer =
<div>默认底部</div> })
// 此时 footer 需要一个默认值
{
  return (
    <>
      <h2>{title}</h2>
      <ul>
        {children}
      </ul>
      {footer}
    </>
  )
}
// 如果需要在列表加元素
export default function App() {
  return (
    <>
      //之前是通过 props 传递 现在通过 children
      //自动接受组件开始和接受的内容
      <List
        title="列表 1"
        footer={
          <p>这是底部内容 1</p>
        }
function List({ children, title, footer =
<div>默认底部</div> })
// 此时 footer 需要一个默认值
{
  return (
    <>
      <h2>{title}</h2>
      <ul>
        {children}
      </ul>
      {footer}
    </>
  )
}
// 如果需要在列表加元素
export default function App() {
  return (
    <>
      //之前是通过 props 传递 现在通过 children
      //自动接受组件开始和接受的内容
      <List
        title="列表 1"
        footer={
          <p>这是底部内容 1</p>
        }
      >
        <li>内容 1</li>
        <li>内容 2</li>
        <li>内容 3</li>
      </List>

      <List
        title="列表 2"
        footer={<p>这是底部内容 2</p>}
      >
        <li>内容 A</li>
        <li>内容 B</li>
        <li>内容 C</li>
      </List>
      <List
        title="列表 3"
        // 此时没设置 footer 会显示默认值
      >
        <li>内容 X</li>
        <li>内容 Y</li>
        <li>内容 Z</li>
      </List>
    </>
  )
}

子组件向父组件传值

父组件给子组件一个自定义事件的设置 再通过事件触发后向父组件传递参数来设置

function Detail ({onActive}){
    //希望告诉父组件内部状态 在 handleClick 函数使用的变更 所以在 handleClick 加入 onACtive 事件并传入 status
    const [status,setStatus]=useState(false)
    function handleClick()
    {
        setStatus(!status)
        onActive(status)
        //每次状态变更 传递一个新值 传递到 function App()
    }
    return (
        <div>
<button onClick={handleClick}>按钮</button>
            <p
                style={{display;staus?
                    'block':'none'}}>
                Detail 的内容</p>

        </div>
    )
}
export default function App(){
    function handleActive(status){
        console.log(status)
    }
    return(
function Detail ({onActive}){
    //希望告诉父组件内部状态 在 handleClick 函数使用的变更 所以在 handleClick 加入 onACtive 事件并传入 status
    const [status,setStatus]=useState(false)
    function handleClick()
    {
        setStatus(!status)
        onActive(status)
        //每次状态变更 传递一个新值 传递到 function App()
    }
    return (
        <div>
<button onClick={handleClick}>按钮</button>
            <p
                style={{display;staus?
                    'block':'none'}}>
                Detail 的内容</p>

        </div>
    )
}
export default function App(){
    function handleActive(status){
        console.log(status)
    }
    return(
    <>
        //如果希望父组件能接受子组件的状态的话需要给子组件设置一个自定义属性 (onActive) 可以理解为事件 用代码决定在何时触发

        <Detail
            onActive={handleActive}></Detail>
        </>

    )
}

同级组件传值

在父组件进行中转

多层级传值

提供了一个多级属性穿透的 hook

import {useState} from "react"
export function Section ({children})
{
    //获取上一级 level
    const level=useContext(LevelContext)
    return (

        <section className="section">
            <LevelContect.Provider
                value={
              level+1
                }>
             {children}</LevelContect.Provider>

        </section>
    )
}
export function Heading({level,children})
{
    const level=useContext(LevelContext)
//设置之后此时全为 h1(若默认值是 1)
//但是 h1 和 section 嵌套会使 h1 显示出从大到小的样式
    switch(level){
        case 1:
            return <h1>{children}</h1>
import {useState} from "react"
export function Section ({children})
{
    //获取上一级 level
    const level=useContext(LevelContext)
    return (

        <section className="section">
            <LevelContect.Provider
                value={
              level+1
                }>
             {children}</LevelContect.Provider>

        </section>
    )
}
export function Heading({level,children})
{
    const level=useContext(LevelContext)
//设置之后此时全为 h1(若默认值是 1)
//但是 h1 和 section 嵌套会使 h1 显示出从大到小的样式
    switch(level){
        case 1:
            return <h1>{children}</h1>
        case 2:
            return <h2>{children}</h2>
        case 3:
            return <h3>{children}</h3>
        case 4:
            return <h4>{children}</h4>
        case 4:
            return <h4>{children}</h4>
        case 5:
            return <h5>{children}</h5>
        case 6:
            return <h6>{children}</h6>
    }
}
const LevelContext=createContext(0)
//不能直接用 通过 useContext
export default function App (){
    return(
    <div>
<section>
<Heading >主标题</Heading>
<section>
<Heading >副标题</Heading>
<Heading >副标题</Heading>
<Heading >副标题 </Heading>
<section>
<Heading>子标</Heading>
<Heading>子标</Heading>
<Heading >子标</Heading>
          <section>
<Heading >子子标题</Heading>
<Heading>子子标题</Heading>
<Heading >子子标题</Heading>
              <section>
<Heading >子子子标题</Heading>
<Heading >子子子标题</Heading>
<Heading >子子子标题</Heading>
                  <section>>
<Heading >子子子子标题 </Heading>
<Heading >子子子子标题 </Heading>
<Heading >子子子子标题 </Heading>
                  </section>
                  </section>
                  </section>
                  </section>
                  </section>
                  </section>
                      </div>)
}

Ps:可能会出现都是 h1 标签但是大小却不同的情况

sectionh1 嵌套时候自然出现的状态

如何更改 useContext 能够获取到的 level 信息

useContext创建的对象 LevelContext 提供一个Provider

context 提供值的一个方式