一起學React--元件定義和元件通訊

蘿蔔突擊發表於2019-03-31

React主打函數語言程式設計,配合上JSX語法,基本上可以把每個模組都封裝為單獨元件,用元件一時爽,一直用一直爽。

1.函式式元件

在React中最簡單的即是建立一個函式式,沒有生命週期的元件,這與 Vue 的單檔案 .vue 一個完整生命週期元件不同,舉個例子。

// 定義weblcome 元件
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
複製程式碼

這裡的props屬性物件是React中元件單向資料傳遞的唯一標示,在函式式元件中,我們可以通過 props.name 來獲取 其他元件傳遞的name 屬性,這點和Vue是沒有本質區別的。

// 子元件 獲取name屬性
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

// 父元件傳入name屬性
const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);

複製程式碼

2.class 元件

函式式元件由於沒有生命週期的定義,雖然簡潔,但是擴充方面較差,我們把上面的welcome,改寫為class元件

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

welcome繼承自React.Component 組基類,在class元件中,作用域為當前元件,所以使用this物件來代替。

class元件有完整的生命週期,當元件插入到DOM中時,會依次呼叫生命週期函式。

render() 是class元件中必須實現的方法 當每次render 被觸發是都會檢查 this.props 和this.state 的變化、 同理適用於任何class 元件的檢查方式 所以在處理函式時,要考慮好應該在元件生命週期的那一步觸發,反之容易涼涼,或影響效能

3.順滑的元件抽取方式

每個class元件, 無論單獨呼叫,還是迴圈呼叫,都有自己的生命週期和單獨的state。

舉個實際場景。 比如:維護一個列表,列表中有, 全部,完成,失敗,進行中,等狀態type。 首先想到的是維護一個type 陣列,然後通過map 迴圈的方式來產生列表 好處是資料操作方便,缺點就是和其他 n個列表公用一個state ,沒有辦法將其中某個item的狀態區分開來

一起學React--元件定義和元件通訊

通過維護一個item元件,每個item都有自己的state,隨心所欲的操作

all in all 每個通過map 迴圈的item, 都可以根據業務考慮封裝為一個元件,因為你定義的時候就是一個變數, 不會像vue 通過v-for 指令渲染,後期抽離的成本不是很大。

Warning 如果shouldComponentUpdate 返回false 則不會render

當元件的props 或者state 變化時會觸發更新。 會依次執行下面的生命週期

  1. static getDerivedStateFromProps()
  2. shouldComponentUpdate() // 必要時來做效能優化,在第一期提過
  3. render() // 必須要用
  4. getSnapshotBeforeUpdate()
  5. componentDidUpdate() // 最常用的元件狀態更新判斷

最比較常用的除了 componentDidMount() 之外,還有 componentDidUpdate() 來判斷元件是否需要更新。

4.使用propTypes進行型別檢查 propsTypes 是React友好的型別檢查,通常和元件搭配使用。

一起學React--元件定義和元件通訊

使用方法非常簡單,上圖

一起學React--元件定義和元件通訊

二、 元件通訊方式 在單向通訊中,最常見的就是通過prop方式。

父 - 子

一起學React--元件定義和元件通訊

子元件定義好item引數 父元件按照propTyes進行傳參 子元件通過 this.props.item 取值

子 - 父


// 子元件
HomeItem.defaultProps = {
  item: {},
  // 定義回撥函式
  fetchData: () => {},
};

HomeItem.propTypes = {
  item: PropTypes.object,
  fetchData: PropTypes.func,
};
複製程式碼
// 在子元件
  handleSuccessDel = () => {
    const successUrl = {
      url: `/xq/statuses/destroy/${this.state.uid}.json`,
      params: {},
    };
    const draftUrl = {
      url: '/xq/statuses/draft/delete.json',
      params: { id: this.props.item.textId },
    };
    const delUrl = this.props.item.typeName === '草稿' ? draftUrl : successUrl;
    httpClient.post(delUrl.url, delUrl.params).then((res) => {
      if (res.success) {
        this.setState({
          showModal: false,
        });
        Toast({ text: '刪除成功', type: 'success' });
        
        // 通過引數執行父元件傳過來的callback 進而引起父元件狀態改變
        this.props.fetchData();
      }
    }).catch((err) => {
      console.error(err);
    });
  };
複製程式碼

相關文章