1.组件传参-父传子
使用 props 传参
// Main.jsx
...
render() {
const { banner } = this.state
return (
<div>
<MainBanner banner={banner} title="123" />
</div>
)
}
...
// MainBanner.jsx
...
import PropTypes from "prop-types"
render() {
const { title, banner } = this.props
return (
<div>
<h2>{title}</h2>
<ul>
{banner.map(item => (
<li key={item.acm}>{item.title}</li>
))}
</ul>
</div>
)
// 类型验证
MainBanner.propTypes = {
banner: PropTypes.array.isRequired,
title: PropTypes.string
}
// 默认参数
MainBanner.defaultProps = {
banner: [],
title: "默认标题"
}
...
2. 组件传参-子传父
import React, { Component } from "react"
import AddCounter from "./AddCounter"
export class App extends Component {
constructor() {
super()
this.state = {
counter: 100
}
}
changeCounter(count) {
this.setState({
counter: this.state.counter + count
})
}
render() {
const { counter } = this.state
return (
<div>
<h2>当前计数: {counter}</h2>
<AddCounter addClick={count => this.changeCounter(count)} />
</div>
)
}
}
export default App
// AddCounter
import React, { Component } from "react"
export class AddCounter extends Component {
addCount(count) {
this.props.addClick(count)
}
render() {
return (
<div>
<button onClick={e => this.addCount(1)}>+1</button>
<button onClick={e => this.addCount(5)}>+5</button>
<button onClick={e => this.addCount(10)}>+10</button>
</div>
)
}
}
export default AddCounter
3. 组件的插槽效果实现
3.1 children 方式实现
import React, { Component } from "react"
import Navbar from "./NavBar"
export class App extends Component {
render() {
return (
<div>
<Navbar>
<div>left</div>
<h2>title</h2>
<i>right</i>
</Navbar>
</div>
)
}
}
export default App
// Navbar
import React, { Component } from "react"
import ProyTypes from "prop-types"
export class Navbar extends Component {
render() {
const { children } = this.props
return (
<div className="nav-bar">
<div className="left">{children[0]}</div>
<div className="center">{children[1]}</div>
<div className="right">{children[2]}</div>
</div>
)
}
}
// 可以使用 props 类型判断来控制传入的内容是元素还是数组
// 当props只有一个children时,此时插槽内容默认为一个元素,而不是数组
Navbar.propTypes = {
// children: ProyTypes.element
children: ProyTypes.array
}
export default Navbar
3.2 props 方式实现
import React, { Component } from "react"
import NavBar2 from "./NavBar2"
export class App extends Component {
render() {
return (
<div>
<NavBar2 leftSlot={<button>按钮</button>} centerSlot={"中心内容"} rightSlot={<i>斜体文字</i>} />
</div>
)
}
}
export default App
// NavBar2
import React, { Component } from "react"
export class NavBar2 extends Component {
render() {
const { leftSlot, centerSlot, rightSlot } = this.props
return (
<div className="nav-bar">
<div className="left">{leftSlot}</div>
<div className="center">{centerSlot}</div>
<div className="right">{rightSlot}</div>
</div>
)
}
}
export default NavBar2
3.3 组件的作用于插槽
import React, { Component } from "react"
import TabControl from "./TabControl"
export class App extends Component {
constructor() {
super()
this.state = {
titles: ["流行", "精选", "新款"],
tabIndex: 0
}
}
indexChange(tabIndex) {
this.setState({ tabIndex })
}
getTabItem(item) {
if (item === "流行") {
return <h2>{item}</h2>
} else if (item === "精选") {
return <button>{item}</button>
} else {
return <i>{item}</i>
}
}
render() {
const { titles, tabIndex } = this.state
return (
<div className="app">
<TabControl titles={titles} tabClick={i => this.indexChange(i)} itemType={item => this.getTabItem(item)} />
<h1>{titles[tabIndex]}</h1>
</div>
)
}
}
export default App
// TabControl/index.jsx
import React, { Component } from "react"
export class TabControl extends Component {
constructor() {
super()
this.state = {
currentIndex: 0
}
}
tabChange(i) {
this.setState({ currentIndex: i })
this.props.tabClick(i)
}
render() {
const { titles, itemType } = this.props
const { currentIndex } = this.state
return (
<div className="tab-control">
{titles.map((title, index) => (
<div className={`item ${currentIndex === index ? "active" : ""}`} key={title} onClick={e => this.tabChange(index)}>
{/* <span className="text">{title}</span> */}
{itemType(title)}
</div>
))}
</div>
)
}
}
export default TabControl
3.4 非父子组件通信-context
3.4.1 Context.Provider
// context/theme-context.js
import React from "react"
const ThemeContext = React.createContext()
export default ThemeContext
// APP.jsx
import ThemeContext from "./context/theme-context"
constructor() {
super()
this.state = {
info: { name: "kobe", age: 30 }
}
}
render() {
const { info } = this.state
return (
<div>
<ThemeContext.Provider value={{ color: "red", size: 30 }}>
<Home {...info} />
</ThemeContext.Provider>
</div>
)
}
// HomeInfo.jsx
import ThemeContext from "./context/theme-context"
render() {
return (HomeInfo: {this.context.color}-{this.context.size})
}
HomeInfo.contextType = ThemeContext
3.4.2 Context.Comsumer
- 函数组件中使用
// context/user-context.js
import React from "react"
const UserContext = React.createContext()
export default UserContext
// HomeBanner.jsx
import ThemeContext from "./context/theme-context"
function HomeBanner() {
return (
<ThemeContext.Consumer>
{value => (
<h2>
Banner Info: {value.color}-{value.size}
</h2>
)}
</ThemeContext.Consumer>
)
}
export default HomeBanner
- 多层嵌套非父子组件通信
// App.jsx
import React, { Component } from "react"
import ThemeContext from "./context/theme-context"
import UserContext from "./context/user-context"
import Home from "./Home"
export class App extends Component {
constructor() {
super()
this.state = {
info: { name: "kobe", age: 30 }
}
}
render() {
const { info } = this.state
return (
<div>
<UserContext.Provider value={{ nickname: "kobe", age: 100 }}>
<ThemeContext.Provider value={{ color: "red", size: 30 }}>
<Home {...info} />
</ThemeContext.Provider>
</UserContext.Provider>
</div>
)
}
}
export default App
// HomeInfo.jsx
import React, { Component } from "react"
import ThemeContext from "./context/theme-context"
import UserContext from "./context/user-context"
export class HomeInfo extends Component {
render() {
return (
<div>
HomeInfo: {this.context.color}-{this.context.size}
<UserContext.Consumer>
{value => (
<h2>
HomeInfo2: {value.nickname}-{value.age}
</h2>
)}
</UserContext.Consumer>
</div>
)
}
}
HomeInfo.contextType = ThemeContext
export default HomeInfo
3.5 使用默认值 defaultValue
当使用的内容不在Context中,此时可以将参数放到 defaultValue,其他组件就可以使用