父子组件
父传子
- 在子组件通过属性传递内容 - 属性=值
- 子组件通过props拿到内容 -props参数
类组件
//父级
render() {
const { banners, productList } = this.state
return (
<div className='main'>
<div>Main</div>
<MainBanner banners={banners} title="轮播图"/>
<MainBanner/>
<MainProductList productList={productList}/>
</div>
)
}
//子
//MainBanner
export class MainBanner extends Component {
// static defaultProps = {
// banners: [],
// title: "默认标题"
// }
constructor(props) {
super(props)
this.state = {}
}
render() {
// console.log(this.props)
const { title, banners } = this.props
return (
<div className='banner'>
<h2>封装一个轮播图: {title}</h2>
<ul>
{
banners.map(item => {
return <li key={item.acm}>{item.title}</li>
})
}
</ul>
</div>
)
}
}
//MainProductList
export class MainProductList extends Component {
render() {
const { productList } = this.props
return (
<div>
<h2>商品列表</h2>
<ul>
{
productList.map(item => {
return <li key={item.acm}>{item.title}</li>
})
}
</ul>
</div>
)
}
}
函数组件
function Child(props){
const {name, age, height} = props
return (
<div>
<p>展示父组件传递过来的数据:{ name + " " +
age + " " + height}</p>
</div>
)
}
export class App extends Component {
render() {
return (
<div className='app'>
<Child name="hhh" age="18" height="18">
</div>
)
}
}
子传父
- 通过传递函数,调用回调函数
- 通过函数的参数传递要传递的数据
//父 传递回调函数
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)}/>
<SubCounter subClick={(count) => this.changeCounter(count)}/>
</div>
)
}
}
//子 把参数传递给回调函数
export class AddCounter extends Component {
addCount(count) {
this.props.addClick(count)
}
render() {
return (
<div>
<button onClick={e => this.addCount(1)}>+1</button>
</div>
)
}
}
export class SubCounter extends Component {
subCount(count) {
this.props.subClick(count)
}
render() {
return (
<div>
<button onClick={e => this.subCount(-10)}>-10</button>
</div>
)
}
}
参数propTypes
- 对于传递给子组件的数据,可能希望进行类型验证
- 可以通过 prop-types 库来进行参数验证;
- zh-hans.reactjs.org/docs/typech…
export class MainBanner extends Component {
// static defaultProps = {
// banners: [],
// title: "默认标题"
// }
constructor(props) {
super(props)
this.state = {}
}
render() {
const { title, banners } = this.props
return (
<div className='banner'>
<h2>封装一个轮播图: {title}</h2>
<ul>
{
banners.map(item => {
return <li key={item.acm}>{item.title}</li>
})
}
</ul>
</div>
)
}
}
// MainBanner传入的props类型进行验证
MainBanner.propTypes = {
banners: PropTypes.array,
title: PropTypes.string
}
// 没有传递,默认值。MainBanner传入的props的默认值
MainBanner.defaultProps = {
banners: [],
title: "默认标题"
}
非父子组件的通信有哪些方式?
事件总线
Context
- Context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props;
- 创建context
- 在要使用的组件,一般是根组件导入context
- 使用<context.Provider>包裹后代组件
- 在要使用的后代组件引入context
- xxxx.contextType = context
- 在render方法中可以通过this.context拿到传递过来的值
// 1.创建一个Context
const ThemeContext = React.createContext({ color: "blue", size: 10 })
{/* 2.普通的Home */}
{/* 第二步操作: 通过ThemeContext中Provider中value属性为后代提供数据 */}
<UserContext.Provider value={{nickname: "kobe", age: 30}}>
<ThemeContext.Provider value={{color: "red", size: "30"}}>
<Home {...info}/>
</ThemeContext.Provider>
</UserContext.Provider>
<Profile/>
export class HomeInfo extends Component {
render() {
// 4.第四步操作: 获取数据, 并且使用数据
console.log(this.context)
return (
<div>
<h2>HomeInfo: {this.context.color}</h2>
<UserContext.Consumer>
{
value => {
return <h2>Info User: {value.nickname}</h2>
}
}
</UserContext.Consumer>
</div>
)
}
}
// 3.第三步操作: 设置组件的contextType为某一个Context
HomeInfo.contextType = ThemeContext
- Context相关API
- React.createContext
- 创建一个需要共享的Context对象:
- 如果一个组件订阅了Context,那么这个组件会从离自身最近的那个匹配的 Provider 中读取到当前的context值;
- defaultValue是组件在顶层查找过程中没有找到对应的Provider,那么就使用默认值
- React.createContext
- Context.Provider
- 每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化:
- Provider 接收一个 value 属性,传递给消费组件;
- 一个 Provider 可以和多个消费组件有对应关系;
- 多个 Provider 也可以嵌套使用,里层的会覆盖外层的数据;
- 当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染;
- Class.contextType
- 挂载在 class 上的 contextType 属性会被重赋值为一个由 React.createContext() 创建的 Context 对象:
- 这能让你使用 this.context 来消费最近 Context 上的那个值;
- 你可以在任何生命周期中访问到它,包括 render 函数中;
- Context.Consumer
- 这里,React 组件也可以订阅到 context 变更。这能让你在 函数式组件 中完成订阅 context。
- 这里需要 函数作为子元素(function as child)这种做法;
- 这个函数接收当前的 context 值,返回一个 React 节点;
- 使用时机:
- 当使用value的组件是一个函数式组件时;
- 当组件中需要使用多个Context时;