ReactP7_React的元件化開發(二)
- 關于super(props)的傳值問題
- 元件通信子傳父
- 元件通信案例
- Context
-
- React.createContext
- Context.Provider
- Class.contextType
- Context.Consumer
這邊是react學習記錄,期間加入了大量自己的了解,用于加強印象,若有錯誤之處還請多多指出
關于super(props)的傳值問題

正常情況下,需要super(props)方法來擷取傳入此元件的參數。如圖所示,super( )方法并沒有去主動擷取props中的參數,是以在随後的console.log(this.props)中列印出來的是undefined,但是在render函數中,卻可以獲得props值,擷取值和super( )沒有關系。這個原因,需要從源碼中去解讀。架構不論我們是否主動擷取并指派this.props值,都會在運作的過程中進行一次對this.props的指派操作,是以在随後是可以直接使用傳過來的props參數的。具體代碼的位置在如圖所示的代碼中
元件通信子傳父
某些情況,我們也需要子元件向父元件傳遞消息:
在vue中是通過自定義事件來完成的——this.$emit([自定義事件名])
在React中同樣是通過props傳遞消息,隻是讓父元件給子元件傳遞一個回調函數,在子元件中調用這個函數即可
個人了解來看,就是告訴子元件一些資訊“A={func}”,其中A是發生的事件名稱,func是發生該事件之後需要執行的事情,或者說需要執行的函數,子元件如果需要了,就會在發生指定的情況之後執行以下A,那麼就會在父元件根據A觸發的情況,執行以下func。和vue不同的是,vue是子元件告訴父元件發生了事情A,然後在A執行func,React是父元件告訴子元件A和func,然後子元件發生并使用了A,對應的調用了父元件之前給的的func
Appjs代碼
import React,{ Component } from "react";
import Child from "./Child"
export default class App extends Component{
constructor(props){
super();
this.state = {
counter:0
}
}
render(){
const {counter} = this.state;
return (
<div>
<h2>{counter}</h2>
<Child add = { e=>{this.Increment()}}/>
</div>
)
}
Increment(){
this.setState({
counter:this.state.counter + 1,
})
}
}
Childjs代碼
import React , {Component} from "react";
export default class Child extends Component{
constructor(props){
super(props);
this.state = {
}
}
render(){
const { add } = this.props;
return(
<button onClick={add}>+1</button>
)
}
}
通俗的講:此處就是父元件寫了方法Increment,并且告訴子元件,發生add事件的話我就會執行Increment,子元件在發生點選事件之後,告訴父元件,發生了add事件需要執行Increment,此時父元件執行了一次Increment函數。基本就是這麼個思路
元件通信案例
制作一個類似于tab的點選顯示效果:直接上代碼
App.js
import React,{ Component } from "react";
import TabControl from "./TabControl"
export default class App extends Component{
constructor(props){
super();
console.log(this.props);//undefined
this.state = {
titles:["A","B","C"],
currentIndex:0,
}
}
render(){
console.log(this.props);//{}
const { titles, currentIndex } = this.state;
return (
<div>
<TabControl itemClick={ index => { this.itemClick(index) }} titles={titles}/>
<h2>{titles[currentIndex]}</h2>
</div>
)
}
itemClick(index){
this.setState({
currentIndex:index
})
}
}
tabControl.js
import React from "react";
import PropTypes from "prop-types"
export default class TabControl extends React.Component{
constructor(props){
super(props);
this.props = props;
this.state = {
currentIndex : 0,
}
}
render(){
const { titles } = this.props;
const { currentIndex } = this.state;
return (
<div className="tab-control">
{
titles.map((item,index)=>{
return(
<div key={item}
className={"tab-item " + (index === currentIndex?"active":"")}
onClick={ e => { this.itemClick(index) }}>
<span>{item}</span>
</div>
)
})
}
</div>
)
}
itemClick(index){
this.setState({
currentIndex:index,
})
const { itemClick } = this.props;
itemClick(index);
}
}
TabControl.propTypes = {
titles:PropTypes.array,
currentIndex:PropTypes.number,
}
style.css
*{
margin: 0;
padding: 0;
}
.tab-control{
display: flex;
text-align: center;
height: 44px;
line-height: 44px;
}
.tab-item{
flex: 1;
}
.tab-item span{
padding: 8px 5px;
}
.tab-item.active span{
border-bottom: solid 2px red;
}
通過這個案例,基本能夠掌握元件通信了,而且這個難度的練習基本能夠應付很多的tab功能需求
Context
這一塊說實話很煩,我也記不太住,大緻了解成有那麼一個框框,這個框框表示的是那些可以被共享的參數,那些被框框給框住的元件,是可以通路到這些共享參數的,具體執行有興趣可以往下看
背景:常見的資料傳遞方式是通過props屬性自上而下(由父到子)進行傳遞,但是一些資料需要在多個元件中進行共享。如果在頂層的App中定義這些資訊,一層層傳遞下去,那麼對于一些中間元件不需要資料的元件來說,是一種備援的操作
Context 提供了一種在元件之間共享此類值的方式,而不必顯式地通過元件樹的逐層傳遞 props,Context 設計目的是為了共享那些對于一個元件樹而言是“全局”的資料。
簡而言之就是提供一種平台,能夠存放供所有元件共同讀取的資料,類似Vuex裡面$store.state青春版
React.createContext
- 建立一個需要共享的Context對象
如果一個元件訂閱了Context,那麼這個元件會從離自身最近的那個比對的 Provider 中讀取到目前的context值
defaultValue是元件在頂層查找過程中沒有找到對應的Provider,那麼就使用預設值
個人了解:建立一個共享資料的框框, 共享的預設資料使用defaultValue存放
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 節點
consumer就是框框裡面需要調用資料的元件,需要套在Provider的裡面,通過回調函數來對資料進行調用
以上就是元件化開發第二部分的全部内容了
感謝coderwhy(王紅元老師)的課程指導
愛生活,愛豬豬