React簡明學習

来源:https://www.cnblogs.com/xiaohuochai/archive/2018/03/26/8541350.html
-Advertisement-
Play Games

[1]JSX [2]樣式設置 [3]組件 [4]State [5]事件處理 [6]列表 [7]表單 [8]propTypes [9]返回多個元素 [10]context ...


前面的話

  React讓組件化成為了前端開發的基本思路,比傳統思路可以更好的控制前端複雜度,舊的開發方法受到了影響,如分離式的HTML/CSS、非侵入式JS、模板語言、MVC、CSS文件、Bootstrap等。在React中,組件把數據翻譯成UI,數據通過組件props屬性傳入,組件自身狀態通過state狀態值來控制。 每個組件都是一個狀態機,也就是聲明式編程。數據有變化,組件自動刷新。本文將詳細介紹React基本概念

 

JSX

  JSX是Javascript的語法擴展(extension),可以讓我們在Javascript中可以編寫像HTML一樣的代碼。

  JSX用來聲明 React 當中的元素,JSX 中使用 JavaScript 表達式,JSX中的表達式要包含在大括弧里

【模板字元串】

  可以在JSX中使用模板字元串

{`Joined in ${time}`}

【屬性】

  可以使用引號來定義以字元串為值的屬性:

const element = <div tabIndex="0"></div>;

  也可以使用大括弧來定義以 JavaScript 表達式為值的屬性:

const element = <img src={user.avatarUrl} />;

  下麵這兩個 JSX 表達式是等價的

<MyComponent message="hello world" />
<MyComponent message={'hello world'} />

【預設為true】

  如果沒有給屬性傳值,它預設為 true

<MyTextBox autocomplete />
<MyTextBox autocomplete={true} />

【擴展屬性】

  如果已經有了個 props 對象,並且想在 JSX 中傳遞它,可以使用 ... 作為擴展操作符來傳遞整個屬性對象。下麵兩個組件是等效的:

function App1() {
  return <Greeting firstName="Ben" lastName="Hector" />;
}

function App2() {
  const props = {firstName: 'Ben', lastName: 'Hector'};
  return <Greeting {...props} />;
}

【return】

  return一定要緊挨著左括弧,否則不生效

【JSX是進步還是倒退】

  長期以來,一直不倡導在HTML中使用onclick,為什麼在JSX中卻要使用onClick這樣的方式來添加事件處理函數呢?

  在React出現之初,很多人對React這樣的設計非常反感,因為React把類似HTML的標記語言和Javascript混在一起了。但是,隨著時間的推移,業界逐漸認可了這種方式,因為大家發現,以前用HTML來代表內容,用CSS代表樣式,用Javascript來定義交互行為,這三種語言分在三種不同的文件裡面,實際上是把不同技術分開管理了,而不是邏輯上的“分而治之”

  根據做同一件事的代碼應該有高耦合性的設計原則,為什麼不把實現這個功能的所有代碼集中在一個文件里呢?

  在JSX中使用onClick來添加事件處理函數,是否代表網頁應用開發兜了一個大圈,最終回到了起點呢?

  不是的,在HTML中直接使用onclick很不專業,因為onclick添加的事件處理函數是在全局環境下執行的,這污染了全局環境,很容易產生意料不到的後果;給很多DOM元素添加onclick事件,可能會影響網頁的性能;對於使用onclick的DOM元素,如果在DOM元素刪除後忘了註銷事件處理函數,可能會造成記憶體泄漏

  上面說的這些問題在JSX中都不存在

  onClick掛載的每個函數,都可以控制在組件範圍內,不會污染全局空間;在JSX中使用了onClick,但並沒有產生直接使用onclick的HTML,而是使用事件委托的方式處理,無論多少個onclick出現,最後都只在DOM樹上添加了一個事件處理函數,掛在最頂層的DOM節點上;因為React控制了組件的生命周期,在unmount時自然能夠清除相關的所有事件處理函數,記憶體泄漏也不再是一個問題

 

樣式設置

【行內樣式】

  當屬性的類型不是字元串類型時,在JSX中必須用花括弧{}把prop值包住。所以style的值有兩層花括弧

  行內樣式使用如下寫法

{{color:'red',backgroundColor:'blue'}}

【圖片】

  圖片的相對引用使用如下寫法

<img src={require('./common/img/128H.jpg')} alt="" />

【CSS引入】

require('./common/style/main.css')

  或者

import '@/assets/global.css'

【class設置】

<div className="test"></div>

【自定義屬性】

<div data-abc="123"></div>

 

組件

  作為軟體設計的通用原則,組件的劃分要滿足高內聚和低耦合。高內聚是指把邏輯緊密相關的內容放在一個組件中。低耦合是指不同組件之間的依賴關係要儘量弱化,也就是每個組件要儘量獨立

  組件從概念上看就像是函數,它可以接收任意的輸入值(稱之為“props”),並返回一個需要在頁面上展示的React元素

  [註意]組件可以嵌套自身

【函數組件】

  定義一個組件最簡單的方式是使用JavaScript函數

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

【類組件】

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

 

prop

  當React遇到的元素是用戶自定義的組件,它會將JSX屬性作為單個對象傳遞給該組件,這個對象稱之為“props”

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);

【只讀性】

  無論是使用函數或是類來聲明一個組件,它決不能修改它自己的props

【隱藏組件】

  讓 render 方法返回 null 可以隱藏組件

【父傳子】

  下麵的例子來展示父級如何通過props把數據傳遞給子級

class ControlPanel extends Component {
  render() {
    return (
      <div>
        <Counter caption="First"/>
        <Counter caption="Second" initValue={10} />
        <Counter caption="Third" initValue={20} />
        <button onClick={ () => this.forceUpdate() }>
          Click me to re-render!
        </button>
      </div>
    );
  }
}

【讀取props】

  下麵的例子展示子級如何讀取父級傳遞來的props

class Counter extends Component {

  constructor(props) {
    super(props);this.state = {
      count: props.initValue
    }
  }

【props檢查】

  一個組件應該規範以下內容:這個組件支持哪些prop,以及每個prop應該是什麼樣的格式。React通過propTypes來支持這些功能

Counter.propTypes = {
  caption: PropTypes.string.isRequired,
  initValue: PropTypes.number
};

Counter.defaultProps = {
  initValue: 0
};

【子傳父】

  React組件要反饋數據在父組件時,可以使用prop。函數類型的prop等於讓父組件交給子組件一個回調函數,子組件在恰當的時機調用函數類型的prop,可以帶上必要的參數,這樣就可以反過來把信息傳遞給父級

  下麵的例子中,onUpdate是子組件向父組件傳遞數據的渠道

//子組件
class Counter extends Component {
  constructor(props) {
    super(props);
    this.onClickIncrementButton = this.onClickIncrementButton.bind(this);
    this.onClickDecrementButton = this.onClickDecrementButton.bind(this);
    this.state = {count: props.initValue}
  }
  onClickIncrementButton() {
    this.updateCount(true);
  }
  onClickDecrementButton() {
    this.updateCount(false);
  }
  updateCount(isIncrement) {
    const previousValue = this.state.count;
    const newValue = isIncrement ? previousValue + 1 : previousValue - 1;
    this.setState({count: newValue})
    this.props.onUpdate(newValue, previousValue)
  }
  render() {
    const {caption} = this.props;
    return (
      <div>
        <button style={buttonStyle} onClick={this.onClickIncrementButton}>+</button>
        <button style={buttonStyle} onClick={this.onClickDecrementButton}>-</button>
        <span>{caption} count: {this.state.count}</span>
      </div>
    );
  }
}
Counter.propTypes = {
  caption: PropTypes.string.isRequired,
  initValue: PropTypes.number,
  onUpdate: PropTypes.func
};
Counter.defaultProps = {
  initValue: 0,
  onUpdate: f => f 
};
export default Counter;
//父組件
class ControlPanel extends Component {
  constructor(props) {
    super(props);
    this.onCounterUpdate = this.onCounterUpdate.bind(this);
    this.initValues = [ 0, 10, 20];
    const initSum = this.initValues.reduce((a, b) => a+b, 0);
    this.state = {sum: initSum};
  }
  onCounterUpdate(newValue, previousValue) {
    const valueChange = newValue - previousValue;
    this.setState({ sum: this.state.sum + valueChange});
  }
  render() {
    return (
      <div>
        <Counter onUpdate={this.onCounterUpdate} caption="First" />
        <Counter onUpdate={this.onCounterUpdate} caption="Second" initValue={this.initValues[1]} />
        <Counter onUpdate={this.onCounterUpdate} caption="Third" initValue={this.initValues[2]} />
        <div>Total Count: {this.state.sum}</div>
      </div>
    );
  }
}
export default ControlPanel;

【局限】

  設想一下,在一個應用中,包含三級或三級以上的組件結構,頂層的祖父級組件想要傳遞一個數據給最低層的子組件,用prop的方式,就只能通過父組件中轉,也許中間那一層根本用不上這個prop,但是依然需要支持這個prop,扮演好搬運工的角色,只因為子組件用得上,這明顯違反了低耦合的設計要求。於是,提出了專門的狀態管理的概念

 

State

  如何組織數據是程式的最重要問題。React組件的數據分為兩種:prop和state。無論prop還是state的改變,都可能引發組件的重新渲染

  狀態state與屬性props十分相似,但是狀態是私有的,完全受控於當前組件。prop是組件的對外介面,state是組件的內部狀態

  由於React不能直接修改傳入的prop,所以需要記錄自身數據變化,就要使用state

【state與prop的區別】

  下麵來總結下state與prop的區別

  1、prop用於定義外部介面,state用於記錄內部狀態

  2、prop的賦值在父組件使用該組件時,state的賦值在該組件內部

  3、組件不可修改prop的值,而state存在的目的就是讓組件來改變的

  組件的state,相當於組件的記憶,其存在意義就是被改變,每一次通過this.setState函數修改state就改變了組件的狀態,然後通過渲染過程把這種變化體現出來

【正確使用state】

  1、不要直接更新狀態,構造函數是唯一能夠初始化 this.state 的地方

  如果直接修改this.state的值,雖然事實上改變了組件的內部狀態,但只是野蠻地修改了state,但沒有驅動組件進行重新渲染。而this.setState()函數所做的事情,就是先改變this.state的值,然後驅動組件重新渲染

// Wrong
this.state.comment = 'Hello';
// Correct
this.setState({comment: 'Hello'});

  2、狀態更新可能是非同步的

  setState是非同步更新,而不是同步更新,下麵是一個例子

setYear(){
  let {year} = this.state
  this.setState({
    year: year + 10 //新值
  })
  console.log(this.state.year)//舊值
}
setYear(){
    setTimeout(() => {
      this.setState({
        year: year + 10 //新值
      })
      console.log(this.state.year)//新值
    })
}

  因為 this.props 和 this.state 可能是非同步更新的,不應該依靠它們的值來計算下一個狀態

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

  要修複它,要使用第二種形式的 setState() 來接受一個函數而不是一個對象。 該函數將接收先前的狀態作為第一個參數,將此次更新被應用時的props做為第二個參數:

// Correct
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));

  3、狀態更新合併

  可以調用 setState() 獨立地更新它們,但React將多個setState() 調用合併成一個調用來提高性能。

componentDidMount() {
    fetchPosts().then(response => {
      this.setState({
        posts: response.posts
      });
    });

    fetchComments().then(response => {
      this.setState({
        comments: response.comments
      });
    });
  }

  這裡的合併是淺合併,也就是說this.setState({comments})完整保留了this.state.posts,但完全替換了this.state.comments

   4、回調函數

  由於setState是非同步更新的,如果需要確定setState更新後,再進行某些操作,可以使用setState的回調函數

this.setState({
  val:value
},() => {
  this.ref.editInput.focus()
})

 

事件處理

  React 元素的事件處理和 DOM元素的很相似。但是有一點語法上的不同:

  1、React事件綁定屬性的命名採用駝峰式寫法,而不是小寫

  2、如果採用 JSX 的語法需要傳入一個函數作為事件處理函數,而不是一個字元串(DOM元素的寫法)

<button onClick={activateLasers}>
  Activate Lasers
</button>

  [註意]在 React 中不能使用返回 false 的方式阻止預設行為。必須明確的使用 preventDefault

【綁定this】

  可以使用bind()方法

this.handleClick = this.handleClick.bind(this);

  也可以使用屬性初始化器語法

  handleClick = () => {
    console.log('this is:', this);
  }

  如果沒有使用屬性初始化器語法,可以在回調函數中使用箭頭函數

class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }
  render() {
    return (
      <button onClick={(e) => this.handleClick(e)}>
        Click me
      </button>
    );
  }
}

  使用這個語法有個問題就是每次 LoggingButton 渲染的時候都會創建一個不同的回調函數。在大多數情況下,這沒有問題。然而如果這個回調函數作為一個屬性值傳入低階組件,這些組件可能會進行額外的重新渲染。通常建議在構造函數中綁定或使用屬性初始化器語法來避免這類性能問題

【傳遞參數】

  以下兩種方式都可以向事件處理程式傳遞參數:

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

  [註意]通過 bind 方式向監聽函數傳參,在類組件中定義的監聽函數,事件對象 e 要排在所傳遞參數的後面

class Popper extends React.Component{
    preventPop(name, e){   
        e.preventDefault();
        alert(name);
    }
    render(){
        return (<a href="https://reactjs.org" onClick={this.preventPop.bind(this,this.state.name)}>Click</a>
        );
    }
}

【原生事件對象】

handleClick(e){
  e.nativeEvent
}

 

 

列表

【keys】

  Keys可以在DOM中的某些元素被增加或刪除的時候幫助React識別哪些元素髮生了變化。因此應當給數組中的每一個元素賦予一個確定的標識

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li key={number.toString()}>
    {number}
  </li>
);

  一個元素的key最好是這個元素在列表中擁有的一個獨一無二的字元串。通常,使用來自數據的id作為元素的key

const todoItems = todos.map((todo) =>
  <li key={todo.id}>
    {todo.text}
  </li>
);

  當元素沒有確定的id時,可以使用序列號索引index作為key

const todoItems = todos.map((todo, index) =>
  <li key={index}>
    {todo.text}
  </li>
);

  [註意]如果列表可以重新排序,不建議使用索引來進行排序,因為這會導致渲染變得很慢

  JSX允許在大括弧中嵌入任何表達式

function NumberList(props) {
  const numbers = props.numbers;
  return (
    <ul>
      {numbers.map((number) =>
        <ListItem key={number.toString()}
                  value={number} />

      )}
    </ul>
  );
}

 

表單

【受控組件】

  在HTML當中,像<input>,<textarea>, 和 <select>這類表單元素會維持自身狀態,並根據用戶輸入進行更新。但在React中,可變的狀態通常保存在組件的狀態屬性中,並且只能用 setState() 方法進行更新

  通過使react變成一種單一數據源的狀態來結合二者。React負責渲染表單的組件仍然控制用戶後續輸入時所發生的變化。相應的,其值由React控制的輸入表單元素稱為“受控組件”

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

  由於 value 屬性是在表單元素上設置的,因此顯示的值將始終為 React數據源上this.state.value 的值。由於每次按鍵都會觸發 handleChange 來更新當前React的state,所展示的值也會隨著不同用戶的輸入而更新

【textarea】

  在HTML當中,<textarea> 元素通過子節點來定義它的文本內容。在React中,<textarea>會用value屬性來代替。這樣的話,表單中的<textarea> 非常類似於使用單行輸入的表單:

<textarea value={this.state.value} onChange={this.handleChange} />

【select】

  在React中,並不使用之前的selected屬性,而在根select標簽上用value屬性來表示選中項。這在受控組件中更為方便,因為只需要在一個地方來更新組件

<select value={this.state.value} onChange={this.handleChange}>
  <option value="grapefruit">Grapefruit</option>
  <option value="lime">Lime</option>
</select>

【多個input】

  有處理多個受控的input元素時,可以通過給每個元素添加一個name屬性,來讓處理函數根據 event.target.name的值來選擇做什麼

class Reservation extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isGoing: true,
      numberOfGuests: 2
    };
    this.handleInputChange = this.handleInputChange.bind(this);
  }

  handleInputChange(event) {
    const target = event.target;
    const value = target.type === 'checkbox' ? target.checked : target.value;
    const name = target.name;
    this.setState({
      [name]: value
    });
  }

  render() {
    return (
      <form>
        <label>
          Is going:
          <input
            name="isGoing"
            type="checkbox"
            checked={this.state.isGoing}
            onChange={this.handleInputChange} />
        </label>
        <br />
        <label>
          Number of guests:
          <input
            name="numberOfGuests"
            type="number"
            value={this.state.numberOfGuests}
            onChange={this.handleInputChange} />
        </label>
      </form>
    );
  }
}

 

propTypes

  要檢查組件的屬性,需要配置特殊的 propTypes 屬性

import PropTypes from 'prop-types';

class Greeting extends React.Component {
  render() {
    return (
      <h1>Hello, {this.props.name}</h1>
    );
  }
}

Greeting.propTypes = {
  name: PropTypes.string
};

  react支持如下驗證

import PropTypes from 'prop-types';

MyComponent.propTypes = {
  // 可以將屬性聲明為以下 JS 原生類型
  optionalArray: PropTypes.array,
  optionalBool: PropTypes.bool,
  optionalFunc: PropTypes.func,
  optionalNumber: PropTypes.number,
  optionalObject: PropTypes.object,
  optionalString: PropTypes.string,
  optionalSymbol: PropTypes.symbol,

  // 任何可被渲染的元素(包括數字、字元串、子元素或數組)。
  optionalNode: PropTypes.node,

  // 一個 React 元素
  optionalElement: PropTypes.element,

  // 也可以聲明屬性為某個類的實例
  optionalMessage: PropTypes.instanceOf(Message),

  // 也可以限制屬性值是某個特定值之一
  optionalEnum: PropTypes.oneOf(['News', 'Photos']),

  // 限制它為列舉類型之一的對象
  optionalUnion: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.number,
    PropTypes.instanceOf(Message)
  ]),

  // 一個指定元素類型的數組
  optionalArrayOf: PropTypes.arrayOf(PropTypes.number),

  // 一個指定類型的對象
  optionalObjectOf: PropTypes.objectOf(PropTypes.number),

  // 一個指定屬性及其類型的對象
  optionalObjectWithShape: PropTypes.shape({
    color: PropTypes.string,
    fontSize: PropTypes.number
  }),

  // 也可以在任何 PropTypes 屬性後面加上 `isRequired` 尾碼
  requiredFunc: PropTypes.func.isRequired,

  // 任意類型的數據
  requiredAny: PropTypes.any.isRequired,

  // 也可以指定一個自定義驗證器。它應該在驗證失敗時返回
  // 一個 Error 對象而不是 `console.warn` 或拋出異常。
  // 不過在 `oneOfType` 中它不起作用。
  customProp: function(props, propName, componentName) {
    if (!/matchme/.test(props[propName])) {
      return new Error(
        'Invalid prop `' + propName + '` supplied to' +
        ' `' + componentName + '`. Validation failed.'
      );
    }
  },

  // 可以提供一個自定義的 `arrayOf` 或 `objectOf` 驗證器,它應該在驗證失敗時返回一個 Error 對象。 它被用於驗證數組或對象的每個值。驗證器前兩個參數的第一個是數組或對象本身,第二個是它們對應的鍵。
  customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
    if (!/matchme/.test(propValue[key])) {
      return new Error(
        'Invalid prop `' + propFullName + '` supplied to' +
        ' `' + componentName + '`. Validation failed.'
      );
    }
  })
};

【限制單個子代】

  使用 PropTypes.element 可以指定只傳遞一個子代

import PropTypes from 'prop-types';

class MyComponent extends React.Component {
  render() {
    const children = this.props.children;
    return (
      <div>
        {children}
      </div>
    );
  }
}

MyComponent.propTypes = {
  children: PropTypes.element.isRequired
};

【屬性預設值】

  可以通過配置 defaultProps 為 props定義預設值

class Greeting extends React.Component {
  render() {
    return (
      <h1>Hello, {this.props.name}</h1>
    );
  }
}

// 為屬性指定預設值:
Greeting.defaultProps = {
  name: 'Stranger'
};

// 渲染 "Hello, Stranger":
ReactDOM.render(
  <Greeting />,
  document.getElementById('example')
);

 

返回多個元素

  React 中一個常見模式是為一個組件返回多個元素。Fragments 可以讓你聚合一個子元素列表,並且不在DOM中增加額外節點

  Fragments 看起來像空的 JSX 標簽:

render() {
  return (
    <>
      <ChildA />
      <ChildB />
      <ChildC />
    </>
  );
}

  [註意]<></> 語法不能接受鍵值或屬性

  另一種使用片段的方式是使用 React.Fragment 組件,React.Fragment 組件可以在 React 對象上使用,<></> 是 <React.Fragment/> 的語法糖

class Columns extends React.Component {
  render() {
    return (
      <React.Fragment>
        <td>Hello</td>
        <td>World</td>
      </React.Fragment>
    );
  }
}

  如果需要一個帶 key 的片段,可以直接使用 <React.Fragment /> 。 一個使用場景是映射一個集合為一個片段數組 — 例如:創建一個描述列表:

function Glossary(props) {
  return (
    <dl>
      {props.items.map(item => (
        <React.Fragment key={item.id}>
          <dt>{item.term}</dt>
          <dd>{item.description}</dd>
        </React.Fragment>
      ))}
    </dl>
  );
}

 

context

  在嵌套層級較深的場景中,不想要向下每層都手動地傳遞需要的 props。這就需要強大的 context API了。其中,react-redux中的provider組件就是使用context實現的

【手動傳遞props】

  下麵是手動傳遞props的例子

class Button extends React.Component {
  render() {
    return (
      <button style={{background: this.props.color}}>
        {this.props.children}
      </button>
    );
  }
}

class Message extends React.Component {
  render() {
    return (
      <div>
        {this.props.text} <Button color={this.props.color}>Delete</Button>
      </div>
    );
  }
}

class MessageList extends React.Component {
  render() {
    const color = "purple";
    const children = this.props.messages.map((message) =>
      <Message text={message.text} color={color} />
    );
    return <div>{children}</div>;
  }
}

【使用context】

  下麵使用context來自動傳遞

  通過在MessageList(context提供者)中添加childContextTypes和getChildContext,React會向下自動傳遞參數,任何組件只要在它的子組件中(這個例子中是Button),就能通過定義contextTypes來獲取參數。

const PropTypes = require('prop-types');
class Button extends React.Component {
  render() {
    return (
      <button style={{background: this.context.color}}>
        {this.props.children}
      </button>
    );
  }
}
Button.contextTypes = {
  color: PropTypes.string
};

class Message extends React.Component {
  render() {
    return (
      <div>
        {this.props.text} <Button>Delete</Button>
      </div>
    );
  }
}

class MessageList extends React.Component {
  getChildContext() {
    return {color: "purple"};
  }
  render() {
    const children = this.props.messages.map((message) =>
      <Message text={message.text} />
    );
    return <div>{children}</div>;
  }
}
MessageList.childContextTypes = {
  color: PropTypes.string
};

  [註意]如果contextTypes沒有定義,那麼context將會是個空對象

【生命周期】

  如果一個組件中定義了contextTypes,那麼下麵這些生命周期函數將會接收到額外的參數,即context對象

constructor(props, context)
componentWillReceiveProps(nextProps, nextContext)
shouldComponentUpdate(nextProps, nextState, nextContext)
componentWillUpdate(nextProps, nextState, nextContext)
componentDidUpdate(prevProps, prevState, prevContext)

【無狀態組件】

  如果contextTypes作為函數參數被定義的話,無狀態函數組件也是可以引用context。以下代碼展示了用無狀態函數組件寫法的Button組件

const PropTypes = require('prop-types');

const Button = ({children}, context) =>
  <button style={{background: context.color}}>
    {children}
  </button>;

Button.contextTypes = {color: PropTypes.string};

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • HTML5 是下一代的 HTML。 什麼是 HTML5? HTML5 將成為 HTML、XHTML 以及 HTML DOM 的新標準。 HTML 的上一個版本誕生於 1999 年。自從那以後,Web 世界已經經歷了巨變。 HTML5 仍處於完善之中。然而,大部分現代瀏覽器已經具備了某些 HTML5 ...
  • 剛纔被博客園官方移出首頁,不服,再發一遍,絕對原創,手打,思路清晰。 首先說一下,我不是阿裡的人,也沒去阿裡面試過,這是某微信群里的一個小伙伴給的,我現在的能力達不到阿裡的要求。不過人沒夢想還不如鹹魚,有能力的話還是想去嘗試一下。本文如有不足,請勿嘲諷,指出不足即可,謝謝。碼字不易,且看且珍惜,轉載 ...
  • 一、jQuery的封裝擴展 1、jQuery中extend方法使用 (掛在到jQuery和jQuery.fn兩對象身上的使用) 1.1、官方文檔定義: jQuery.extend Merge the contents of two or more objects together into the ...
  • 一、常見的web安全及防護原理 1.sql註入原理 就是通過把sql命令插入到web表單遞交或輸入功能變數名稱或頁面請求的查詢字元串,最終達到欺騙伺服器執行惡意的SQL命令。 防護,總的來說有以下幾點: 1、永遠不要信任用戶的輸入,要對用戶的輸入進行校驗,可以通過正則表達式,或限制長度,對單引號雙“--”進 ...
  • 在使用 Angular 進行開發中,我們常用到 Angular 中的綁定——模型到視圖的輸入綁定、視圖到模型的輸出綁定以及視圖與模型的雙向綁定。而這些綁定的值之所以能在視圖與模型之間保持同步,正是得益於Angular中的變化檢測。 ...
  • 什麼是正則表達式 正則表達式是用於匹配字元串中字元組合的模式。在 JavaScript中,正則表達式也是對象。這些模式被用於 RegExp 的 exec 和 test 方法, 以及 String 的 match、replace、search 和 split 方法。 正則表達式存在於大部分的編程語言, ...
  • href=”javascript:void(0);”這個的含義是,讓超鏈接去執行一個js函數,而不是去跳轉到一個地址,而void(0)表示一個空的方法,也就是不執行js函數。 為什麼要使用href=”javascript:void(0);” javascript:是偽協議,表示url的內容通過jav ...
  • function timeToMillion(startStr, endStr) { var times; if(endStr){ var startT = new Date(startStr).getTime() var endT = new Date(endStr).getTime() time... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...