组件多级传递
function ProfileHeader(props) {
return (
<div>
<p>用户昵称: {props.nickname}</p>
<p>用户等级: {props.level}</p>
</div>
)
}
class Profile extends Component{
render() {
return (
<div>
<ProfileHeader {...this.props} />
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
)
}
}
export default class ContextTest extends Component {
constructor(props) {
super(props);
this.state = {
nickname:"kevin",
level:1
}
}
render() {
return (
<div>
<Profile nickname={this.state.nickname} level={this.state.level}/>
</div>
)
}
}
- 存在问题
多级传递参数会是代码增多,不利于维护
使用 Context
类组件使用 Context
步骤
- 创建一个需要共享的Context对象(写在组件外部)
const MyContext = React.createContext(defaultValue)
- 在需要的组件中挂载(写在组件外部)
组件.contextType = MyContext;
- 默认值使用(拥有源数据的组件中)
<Profile/>
- 自定义值使用 这里如果传值不够,默认值不会覆盖,而是完全丢弃默认值
<MyContext.Provider value={{nickname: "kevin", level: 99}}>
<Profile/>
</MyContext.Provider>
- 注意点
* 在该组件的所有生命周期都可以拿到this.context值
* MyContext.Provider嵌套时,组件会寻找距离最近的一个Provider值
完整代码流程
const MyContext = React.createContext({nickname: "kevin", level: 1})
/**
* 1. 如果一个组件订阅了Context,那么这个组件会从离自身最近的那个匹配的 Provider 中读取到当前的context值;
* 2. defaultValue是组件在顶层查找过程中没有找到对应的Provider,那么就使用默认值
*/
class ProfileHeader extends Component{
componentDidMount() {
let value = this.context
console.log("componentDidMount", value);
}
componentDidUpdate(prevProps, prevState, snapshot) {
let value = this.context
console.log("componentDidUpdate", value);
}
componentWillUnmount() {
let value = this.context
console.log("componentWillUnmount", value);
}
render() {
return (
<div>
<p>用户昵称: {this.context.nickname}</p>
<p>用户等级: {this.context.level}</p>
</div>
)
}
}
ProfileHeader.contextType = MyContext;
class Profile extends Component {
render() {
return (
<div>
<ProfileHeader/>
<p>其他内容</p>
</div>
)
}
}
export default class ContextTest extends Component {
constructor(props) {
super(props);
this.state = {
nickname: "kevin",
level: 1
}
}
render() {
return (
<div>
<MyContext.Provider value={{nickname: "kevin", level: 99}}>
<div>-------- 自定义Provider ----------</div>
<Profile/>
</MyContext.Provider>
<div>-------- 默认 ----------</div>
<Profile/>
</div>
)
}
}
image.png
函数组件使用 Context
步骤
- 创建一个需要共享的Context对象(写在组件外部)
const MyContext = React.createContext(defaultValue)
- 在子组件中(写在组件内部)
return (
<div>
<MyContext.Consumer>
{
data=> {
return (
<div>
<h2>用户昵称: {data.nickname}</h2>
<h2>用户等级: {data.level}</h2>
</div>
)
}
}
</MyContext.Consumer>
</div>
)
- 在父组件中默认使用(拥有源数据的组件中)
<Profile/>
- 自定义值使用 这里如果传值不够,默认值不会覆盖,而是完全丢弃默认值,并且取最近的Provider
<MyContext.Provider value={{nickname: "kevin", level: 99}}>
<MyContext.Provider value={{nickname: this.state.nickname, level: this.state.level}}>
<Profile/>
</MyContext.Provider>
</MyContext.Provider>
- 注意点
* 函数组件不需要这步
// ProfileHeader.contextType = MyContext;
* MyContext.Provider嵌套时,组件会寻找距离最近的一个Provider值
完整代码流程
const MyContext = React.createContext({nickname: "kevin", level: 1})
function ProfileHeader() {
return (
<div>
<MyContext.Consumer>
{
value => {
return (
<div>
<h2>用户昵称: {value.nickname}</h2>
<h2>用户等级: {value.level}</h2>
</div>
)
}
}
</MyContext.Consumer>
</div>
)
}
// 函数组件不需要这步
// ProfileHeader.contextType = MyContext;
class Profile extends Component {
render() {
return (
<div>
<ProfileHeader/>
<p>其他内容</p>
</div>
)
}
}
export default class ContextTest extends Component {
constructor(props) {
super(props);
this.state = {
nickname: "jeff",
level: 9
}
}
render() {
return (
<div>
<MyContext.Provider value={{nickname: "kevin", level: 99}}>
<MyContext.Provider value={{nickname: this.state.nickname, level: this.state.level}}>
<Profile/>
</MyContext.Provider>
</MyContext.Provider>
<p>----- 默认 -----</p>
<Profile/>
</div>
)
}
}
image.png
END
网友评论