React进阶学习
组件通讯
简单来说,就是组件之间共享数据
props
作用:接收传递给组件的数据
import React from 'react'
import ReactDOM from 'react-dom';
// 创建一个组件
class Prop extends React.Component {
constructor(props){
super(props)
}
render() {
console.log(this.props);
return (
<div>我是Prop {this.props.name}</div>
)
}
}
ReactDOM.render(<Prop
name="zs"
age={20}
list={['111', '222', '333']}
fn={() => console.log("这是一个函数")}
dom={ <div>这是一个div</div> }
/>, document.getElementById('root'))
特点:
1.传递的可以是任意类型的数据
2.props是只读的对象,无法修改
3.使用构造函数需要先引入,再使用
组件之间传递数据
1.父组件向子组件传递数据
import React from 'react'
// 创建一个组件
class Parent extends React.Component {
state = {
name:'zs',
age:20
}
render(){
return (
<div>父组件中的数据{this.state.name}
<Chird name={this.state.name} />
</div>
)
}
}
// 子组件
class Chird extends React.Component {
render(){
return (
<div>子组件中的数据:{this.props.name}</div>
)
}
}
export default Parent
2.子组件向父组件传递数据
import React from 'react'
// 创建一个组件
class Parent extends React.Component {
state = {
name:'zs',
age:20
}
render(){
return (
<div className="parent">父组件中的数据{this.state.name}
<Chird name={this.state.name} getMsg={this.getMsg} />
</div>
)
}
// 向子组件传递一个函数
getMsg = (msg) => {
this.setState({
chirdMsg:msg
})
// msg就是接收到的数据
}
}
// 子组件
class Chird extends React.Component {
state = {
msg:'这是向父组件传递的数据'
}
render(){
return (
<div className="chird">子组件中的数据:{this.props.name}
<button onClick={this.handleMsg}>向父组件传递数据</button>
</div>
)
}
// 事件函数
handleMsg = () => {
// 调用父组件传递过来的函数
this.props.getMsg(this.state.msg)
}
}
export default Parent
3.兄弟组件之间传递数据:
思路:要传递数据的组件先将数据传递给公共的父组件,父组件接收到数据再将数据传递给接收数据的子组件
import React from 'react'
// 创建一个组件
class Parent extends React.Component {
state = {
name:'zs',
age:20
}
render(){
return (
<div className="parent">父组件中的数据:{this.state.chirdMsg}
{/* 接收到子组件2传递的数据,再传递给子组件1 */}
<Chird1 name={this.state.chirdMsg2} getMsg={this.getChird1Msg} />
<Chird2 name={this.state.name} getMsg={this.getChird2Msg} />
</div>
)
}
// 向子组件传递一个函数
getChird1Msg = (msg) => {
// 获取子组件1传递的数据
this.setState({
chirdMsg1:msg
})
// msg就是接收到的数据
}
// 向子组件2传递一个函数
getChird2Msg = (msg) => {
// 获取子组件2传递过来的数据
this.setState({
chirdMsg2:msg
})
// msg就是接收到的数据
}
}
// 子组件
class Chird1 extends React.Component {
state = {
msg:'老爸你去吃饭'
}
render(){
return (
<div className="chird">子组件2传递过来的数据:{this.props.name}
<button onClick={this.handleMsg}>向父组件传递数据</button>
</div>
)
}
// 事件函数
handleMsg = () => {
// 调用父组件传递过来的函数
this.props.getMsg(this.state.msg)
}
}
// 子组件2
// 子组件
class Chird2 extends React.Component {
state = {
msg:'大哥你去吃饭'
}
render(){
return (
<div className="chird">子组件中的数据:{this.props.name}
<button onClick={this.handleMsg}>向子组件1传递数据</button>
</div>
)
}
// 事件函数
handleMsg = () => {
// 调用父组件函数先向父组件传递数据
this.props.getMsg(this.state.msg)
}
}
export default Parent
Props中的chirdren属性
演示:
import React from 'react'
import ReactDOM from 'react-dom';
// import Prop from './Prop'
import './index.css'
class One extends React.Component {
render() {
return (
<div className="one">
<div>下面的是chirden属性</div>
{this.props.children}
</div>
)
}
}
ReactDOM.render(
<One>
<p>这里的p标签可以通过One组件中的chirden属性获取</p>
</One>,
document.getElementById('root'))
Props校验
作用,让我们对于props外来输入的输入作一个格式的检查
// 引入prop-types进行校验
import PropTypes from 'prop-types'
// 添加校验
One.propTypes = {
// 这里规定了One这个组件中传入的arr只能是一个数组
arr: PropTypes.array
}
更多校验规则示例
// 添加校验
One.prototype = {
a:PropTypes.number, //a的类型:数值(number)
tag:PropTypes.element,// 属性 tag的类型:React元素(element)
fn:PropTypes.func.isRequired,// 属性fn的类型:函数(func)并且为必填项
filter:PropTypes.shape({ // 属性filter的类型:对象({area: ‘上海',price: 1999})
area:PropTypes.string,
price:PropTypes.number
})
}
Props默认值:
class One extends React.Component {
render() {
return (
<div className="one">
{/* 这里也能正常显示 */}
props的默认值{this.props.pageLength}
</div>
)
}
}
One.defaultProps = {
pageLength:10
}
// 这里不传入参数
ReactDOM.render(<One />,document.getElementById('root'))
Context传递数据
嵌套多层传递数据
通过Context中两个组件
Provider:用来提供数据
Consumer:用来消费数据
import React from 'react'
// 创建一个Context
const {Provider, Consumer} = React.createContext()
// 创建一个祖宗组件
class Parent extends React.Component {
state = {
msg:'传递数据给three'
}
render(){
return (
<Provider value={this.state.msg}>
<div className="Parent">
<One />
</div>
</Provider>
)
}
}
class One extends React.Component {
render(){
return (
<div className="one">
<Two />
</div>
)
}
}
class Two extends React.Component {
render(){
return (
<div className="two">
<Three />
</div>
)
}
}
class Three extends React.Component {
render(){
return (
<div className="three">
<Consumer>{data => <span>我接收到的数据:{data}</span> }</Consumer>
</div>
)
}
}
export default Parent
组件生命周期
创建时(挂载阶段)
执行时机:页面加载时
constructor(创建组件阶段,最先执行)
作用:初始化state,为事件绑定this
render(每次组件渲染都会触发)
进行UI的渲染
注意:不能再此钩子函数中调用setState,因为每次调用,会使得UI发生变化,从而反复调用render
componentDidMount(完成DOM渲染之后触发)
1.获取DOM元素
2.发送网络请求
更新时
render(先执行)
触发时机:
1.有新的props数据传入
2.setState(),state中的数据发生改变时
3.forceUpdate,调用这个方法,强制更新
componentDidUpdate(reder执行之后)
作用:
1.获取DOM元素
2.发送网络请求(需要放在一个if语句中,防止渲染数据导致递归)
如果要使用setState(),那必须要放在一个if条件语句中
卸载阶段
钩子函数:componentWillUnmount
组件卸载时调用
作用:清理工作(比如清理定时器)
参考视频学习:
链接