以前可以使用一層一層的往下傳遞,這種可以解決需求,
1.父組件往孫子組件傳值:
App.js
import React, { Component } from 'react'
import Profile from './Profile'
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
nikename:"coderhzc",
level:88
}
}
render() {
const {nikename,level} = this.state
return (
<div>
<Profile nikename={nikename} level={level}/>
</div>
)
}
}
profile.js文件(注意是函數(shù)組件)
import React from 'react';
import ProfileHeader from './ProfileHeader';
export default function Profile(props) {
// 從父組件傳遞過(guò)來(lái)的
console.log(props,"profile");
return (
<div>
<ProfileHeader nikename={props.nikename} level={props.level}/>
<ul>
<li>設(shè)置1</li>
<li>設(shè)置2</li>
<li>設(shè)置3</li>
<li>設(shè)置4</li>
</ul>
</div>
)
}
ProfileHeader.js 是profile.js 的子文件 (注意是函數(shù)組件)
import React from "react";
export default function ProfileHeader(props) {
console.log(props,"ProfileHeaderProfileHeaderProfileHeader");
return (
<div>
<h2>用戶昵稱: {props.nikename}</h2>
<h2>用戶等級(jí): {props.level}</h2>
</div>
);
}
實(shí)際截圖
** 以上可以實(shí)現(xiàn)但是非父子組件就搞不定了 **
補(bǔ)充以上缺陷使用屬性展開(kāi) {...props},就可以省略Profile.js中的那段多余的傳值
2. 跨組件通訊Context應(yīng)用場(chǎng)景
Context相關(guān)API
(1) React.createContext
--創(chuàng)建一個(gè)需要共享的Context對(duì)象:
-- 如果一個(gè)組件訂閱了Context蓝翰,那么這個(gè)組件會(huì)從離自身最近的那個(gè)匹配的 Provider 中讀取到當(dāng)前的context值陷遮;
-- defaultValue是組件在頂層查找過(guò)程中沒(méi)有找到對(duì)應(yīng)的Provider煞檩,那么就使用默認(rèn)值
const myContext = React.create
(2) Context.Provider
-- 每個(gè) Context 對(duì)象都會(huì)返回一個(gè) Provider React 組件尘分,它允許消費(fèi)組件訂閱 context 的變化:
-- Provider 接收一個(gè) value 屬性,傳遞給消費(fèi)組件茎截;
-- 一個(gè) Provider 可以和多個(gè)消費(fèi)組件有對(duì)應(yīng)關(guān)系;
-- 多個(gè) Provider 也可以嵌套使用,里層的會(huì)覆蓋外層的數(shù)據(jù)斋配;
-- 當(dāng) Provider 的 value 值發(fā)生變化時(shí)孔飒,它內(nèi)部的所有消費(fèi)組件都會(huì)重新渲染灌闺;
<MyContext.Provider value={/*某個(gè)值*/}>
(3) Class.contextType
-- 掛載在 class 上的 contextType 屬性會(huì)被重賦值為一個(gè)由 React.createContext() 創(chuàng)建的 Context 對(duì)象:
-- 這能讓你使用 this.context 來(lái)消費(fèi)最近 Context 上的那個(gè)值; p 你可以在任何生命周期中訪問(wèn)到它坏瞄,包括 render 函數(shù)中桂对;
MyClass.contextType = MyContext
(4) Context.Consumer
-- 這里,React 組件也可以訂閱到 context 變更鸠匀。這能讓你在 函數(shù)式組件 中完成訂閱 context蕉斜。
-- 這里需要 函數(shù)作為子元素(function as child)這種做法;
-- 這個(gè)函數(shù)接收當(dāng)前的 context 值缀棍,返回一個(gè) React 節(jié)點(diǎn)宅此;
<MyContext.Consumer>
{value => /*基于context值進(jìn)行渲染*/}
</MyContext.Consumer>
(4.1) Class 類(lèi)組件的具體使用代碼如下:
import React, { Component } from "react";
// 1.創(chuàng)建Context對(duì)象
// defaultValue是組件在頂層查找過(guò)程中沒(méi)有找到對(duì)應(yīng)的Provider,那么就使用默認(rèn)值
// const UserContext = React.createContext(defaultValue)
export const UserContext = React.createContext({
nikename: "aaaaa",
level: -100,
});
// 組件
// 3. 具體的使用方式,記住不能使用函數(shù)組件
class ProfileHeader extends Component {
render() {
console.log(this.context);
return (
<div>
<h2>用戶昵稱: {this.context.nikename}</h2>
<h2>用戶等級(jí): {this.context.level}</h2>
</div>
);
}
}
// 4. 把創(chuàng)建的Context對(duì)象賦值給ProfileHeader的contextType就可以在孫子組件中拿到從爺爺組件傳遞的數(shù)據(jù)了
ProfileHeader.contextType = UserContext;
function Profile(props) {
return (
<div>
<ProfileHeader />
<ul>
<li>設(shè)置1</li>
<li>設(shè)置2</li>
<li>設(shè)置3</li>
<li>設(shè)置4</li>
</ul>
</div>
)
}
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
objName: {
nikename: "coderhzc",
level: 88,
},
};
}
render() {
return (
<div>
{/* 2.具體使用 */}
{/*
(1) Provider 接收一個(gè) value 屬性爬范,傳遞給消費(fèi)組件父腕;
(2) 當(dāng) Provider 的 value 值發(fā)生變化時(shí),它內(nèi)部的所有消費(fèi)組件都會(huì)重新渲染青瀑;
*/}
<UserContext.Provider value={this.state.objName}>
<Profile />
</UserContext.Provider>
</div>
);
}
}
實(shí)際截圖
### (4.2) 函數(shù)組件的具體使用代碼如下:
import React, { Component } from "react";
// 1.創(chuàng)建Context對(duì)象
// defaultValue是組件在頂層查找過(guò)程中沒(méi)有找到對(duì)應(yīng)的Provider璧亮,那么就使用默認(rèn)值
// const UserContext = React.createContext(defaultValue)
const UserContext = React.createContext({
nikename: "aaaaa",
level: -100,
});
// 組件
// 3. 函數(shù)組件的具體使用
function ProfileHeader() {
return (
<div>
<UserContext.Consumer>
{
value => {
console.log(value);
return (
<div>
<h2>用戶昵稱: {value.nikename}</h2>
<h2>用戶等級(jí): {value.level}</h2>
</div>
);
}
}
</UserContext.Consumer>
</div>
);
}
function Profile(props) {
return (
<div>
<ProfileHeader />
<ul>
<li>設(shè)置1</li>
<li>設(shè)置2</li>
<li>設(shè)置3</li>
<li>設(shè)置4</li>
</ul>
</div>
);
}
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
objName: {
nikename: "coderhzc11",
level: 88,
},
};
}
render() {
return (
<div>
{/* 2.具體使用 */}
{/*
(1) Provider 接收一個(gè) value 屬性,傳遞給消費(fèi)組件斥难;
(2) 當(dāng) Provider 的 value 值發(fā)生變化時(shí)枝嘶,它內(nèi)部的所有消費(fèi)組件都會(huì)重新渲染;
*/}
<UserContext.Provider value={this.state.objName}>
<Profile />
</UserContext.Provider>
</div>
);
}
}
實(shí)際截圖
5. 多個(gè)Context使用代碼如下(不推薦做):
import React, { Component } from 'react';
// 創(chuàng)建Context對(duì)象
const UserContext = React.createContext({
nickname: "aaaa",
level: -1
})
const ThemeContext = React.createContext({
color: "black"
})
function ProfileHeader() {
// jsx -> 嵌套的方式
return (
<UserContext.Consumer>
{
value => {
return (
<ThemeContext.Consumer>
{
theme => {
return (
<div>
<h2 style={{color: theme.color}}>用戶昵稱: {value.nickname}</h2>
<h2>用戶等級(jí): {value.level}</h2>
<h2>顏色: {theme.color}</h2>
</div>
)
}
}
</ThemeContext.Consumer>
)
}
}
</UserContext.Consumer>
)
}
function Profile(props) {
return (
<div>
<ProfileHeader />
<ul>
<li>設(shè)置1</li>
<li>設(shè)置2</li>
<li>設(shè)置3</li>
<li>設(shè)置4</li>
</ul>
</div>
)
}
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
nickname: "kobe",
level: 99
}
}
render() {
return (
<div>
<UserContext.Provider value={this.state}>
<ThemeContext.Provider value={{ color: "red" }}>
<Profile />
</ThemeContext.Provider>
</UserContext.Provider>
</div>
)
}
}