import React from 'react'
import App from './App'
// 1.父传子、
// 2.子传父
class ComCent extends React.Component {
// 组件的props特点:
// 1.可以给组件传递任意类型的数据
// 2.props是只读的对象,只能读取属性的值,无法修改对象
// 3.注意:使用类组件时,如果写了构造函数,应该将props传递给super(),否则,无法在构造函数中获取到props
constructor (props) {
super(props)
}
state = {
msg: '我是父组件', // 这是父组件的值
childrenMsg: '父组件传给子组件的值'
}
// 父组件接收子组件方法
getChildMsg = (msg) => {
console.log('接收子组件数据', msg)
this.setState({
msg: msg // 这是父组件的值
})
}
render() {
return (
<div>
<h1>子传父</h1>
<h2>{this.state.msg}</h2>
<Children getChildMsg={this.getChildMsg} childrenMsg={this.state.childrenMsg} />
</div>
)
}
}
class Children extends React.Component {
handleClick = () => {
// 直接用props调用里面的函数
this.props.getChildMsg('我是子组件传递给父组件的值')
}
render () {
return (
<div>
<hr></hr>
<h1>父传子</h1>
<h3>我是子组件,----分割线---这个父组件传给子组件的{this.props.childrenMsg}</h3>
<button onClick={this.handleClick}>点我子组件给父组件传递props值</button>
</div>
)
}
}
// 3.兄弟组件之间的传值
class ParentCom extends React.Component {
state = {
num: 0
}
// 写一个函数接收兄弟2组件传回来的值
returnAdd = () => {
this.setState({
num: this.state.num + 1
})
}
// 这是父组件,两个兄弟组件要通过父组件来进来交互
render () {
return (
<div>
我是父组件
{/* 调用第一个兄弟组件 */}
<Child1Com num={this.state.num} />
<Child1Com num={this.state.num}>我是第一个兄弟组件</Child1Com>
<Child1Com num={this.state.num}>
{
() => console.log('这是一个函数节点')
}
</Child1Com>
{/* 调用第二个兄弟组件 */}
<Child2Com returnAdd={this.returnAdd} />
</div>
)
}
}
function Child1Com (props) {
// 调用第一个组件中传过来的函数节点
props.children()
// 这是第一个兄弟组件
return (
<div>
{/* props.children就是组件引入的文本节点,只要组件有传值,接收组件就有props */}
<p>{props.children}</p>
<h1>计数器:{props.num} </h1>
</div>
)
}
function Child2Com (props) {
function addNumber () {
props.returnAdd()
}
// 这是第二个兄弟组件
return (
<div>
<button onClick={() => props.returnAdd()}>+1</button>
{/* <button onClick={addNumber}>+1</button> */}
</div>
)
}
// ---------------二:Context---------------------
// Context: 用来传递数据的,比如爷爷要传给孙子,或者爷爷传给孙子的孙子,
// 如果按组件传值的话就要一层一层往下传,这个时候就要用到Context
// 使用步骤:
// 1.调用React.createContext()创建Provider(提供数据)和Consumer(消费数据)两个组件
// const {Provider, Consumer} = React.createContext()
// 2.使用Provider组件作为父节点
// <Provider>
// <div>
// <Child1Com />
// </div>
// </Provider>
// 3.设置value属性,表示要传递的数据
// <Provider value="pink"></Provider>
// 4.调用Consumer组件接收数据
// <Consumer>
// {data => <span>data参数表示接收到的数据--{data}</span>}
// </Consumer>
const {Provider, Consumer} = React.createContext()
class GrandParentCom extends React.Component {
// 这是父组件,两个兄弟组件要通过父组件来进来交互
render () {
return (
<Provider value="pink">
<div>
我是爷爷组件
{/* 调用下一级子组件 */}
<Child1 />
</div>
</Provider>
)
}
}
function Child1 () {
// 这是第一个子组件
return (
<div>
<h1>我是爸爸组件,在这里调用孙子组件 </h1>
<Child2 />
</div>
)
}
function Child2 () {
// 这是孙子组件
return (
<div>
<Consumer>
{
data => <span>我是孙子组件,越过父组件,直接从爷爷组件拿值,
拿的值是:--{data}
</span>
}
</Consumer>
</div>
)
}
// ----------------三、props深入-----props的校验----------------------
// props校验
// 1.props校验:允许在创建组建的时候,就指定props的类型、格式等
// 2.作用:捕获使用组件时因为props导致的错误,给出明确的错误提示
// 增加组件的健壮性
// App.propTypes = {
// colors: PropTypes.array // 定义colors为数组格式
// }
// 使用步骤:
// 1.安装包: prop-types(npm i props-types)
// 2.导入prop-types包
// import PropTypes from 'prop-types'
// 3.使用组件名.propTypes = {}来给组件的props添加校验规则
// 4.校验规则通过PropTypes对象来指定
// ParentCom.propTypes = {
// num: PropTypes.number
// num: PropTypes.array
// }
// 常见类型:1. array(数组)、bool(布尔)、func(函数)、number(数值)、
// Object(对象)、string(字符串)
// 2.React元素类型: element
// 3. 必填项:isRequired
// 4.如果是对象则用shape()方法包裹起来
// ParentCom.propTypes = {
// filter: PropTypes.shape({
// area: PropTypes.string,
// areaList: PropTypes.array
// })
// }
// ----------------四:设置组件默认值-------------------------------
// 如果组件中没有传默认值,那么子组件中用props调用的就是这个默认值
function DefaultProps (props) {
return (
<div>
拿到默认值: {props.pageSize}
</div>
)
}
DefaultProps.defaultProps = {
pageSize: 10 // 未传入props时才有效,有传入的以传入为主
}
// export default ComCent;
// export default ParentCom;
// export default GrandParentCom;
export default DefaultProps;