React元件隔離

北宸南蓁發表於2018-08-19

用技術改變生活,用生活完善技術。來自攜程(旅悅)一枚向全棧方向努力奔跑的前端工程師。
微信同步:wDxKn89

前言

元件隔離適用範圍 同一個頁面引用多個相同的自定義公共元件(該類元件擁有自己的Redux)並且這些元件之間有互動。 案例背景 在一個頁面中存在兩個相同的公共元件(A),在頁面處理中,對A元件進行操作,有一些重要的資料被存入到A元件的對應的Redux中。 如果該頁面只存在一個A元件,不管進行如何的操作,資料都是一份。但是如果該頁面中存在多個A元件,在對第一個A元件進行資料處理之後,資料存入到Rudex中。此時在對另一個A元件進行相同的操作步驟,但是存入的資料和第一個A元件的儲存在Redux中的資料有差別,此時在第二個A元件的操作就會影響第一個A元件的資料。

原因:由於頁面中引用的是相同的元件,在進行資料處理的時候,都會存在到Redux中,而該元件的Redux在記憶體中只是儲存了一份。

這就類似於如下操作

let ob1 = new Object();======類似===>定義了一個元件
ob1.name = 'haha';=========類似====>進行資料處理的時候,將元件的一些資料存入到對應的Redux中。
==============華麗的分割線==================
ob1.name ="hehe";=========類似=====>此處類似於第二個元件進行相同的操作,將對應的Redux中的資料進行了變化,該變化會影響到上面的程式碼。
複製程式碼

利用Provider

在需要處理元件隔離的頁面中引用如下程式碼

import { Provider } from 'react-redux';[Provider屬於react-redux](https://github.com/reactjs/react-redux/blob/master/docs/api.md#provider-store)
import { createStore } from 'redux'   ===>用於生成總的Store
import { Router, browserHistory } from 'react-router';
複製程式碼

在元件的constructor中進行變數的初始化

export default class PersonComponent extends Component {
  constructor(props,context){
    super(props,context);
    this.store1 = createStore(reducer);  ===>此處的reducer是你自己的頁面的reducer
  }
  render(){
      //....
  }
}
複製程式碼

關於createStore 處理需要隔離的元件

render(){
    <div>
        <A/>
        <Provider store={this.store1}>  ===>此處的store1是根據你頁面的reducer構建的
             <A/>  ==>此處為需要隔離的元件
        </Provider>
    </div>
}
複製程式碼

基於如上操作,第二個A元件被成功的隔離出整個Store樹之外(換句話說,該A元件自己定義了一套Store)

但是,元件隔離是為了在操作之後,擁有相同的Redux的元件在進行相同的操作步驟之後,互相不被影響。所以,需要根據剛才在第二步構建的Store1來進行對應的action的dispatch.

this.store1.getState().xxx   ===>此處的xxx是在rootReducer.js中combineReducers引用的A元件的Redux的同名State(Note:此處也有對應的方法起一個與Redux不同的名字,自行百度吧)
上面是用於獲取A元件中state資料的,
this.store1.dispatch(yyy(param))  ===>此處的yyy是在A元件的ActionCreator   (該用法請參考Redux官網)
複製程式碼

上面一行程式碼使用者傳送一個action

利用第三方庫multireducer

multireducer該庫的主要目的就是為了實現元件隔離。

對應的github地址 核心思想:A utility to wrap many copies of a single Redux reducer into a single key-based reducer.

專案中引用multireducer

npm install --save multireducer
複製程式碼

在元件定義處處理

引用connectMultireducer

import {connectMultireducer} from 'multireducer';
複製程式碼

元件與Redux進行關聯

@connectMultireducer(
  (key, state) => ({count: state.multireducer[key].count}),
  {increment}
)
複製程式碼

此處的處理方式和華南城專案中@connect的用法類似 主要的區別在與該方法中第二個引數為需要隔離元件的redux.js

在元件呼叫除處理

<A multireducerKey="1" />
 <A multireducerKey="2" />
 <A multireducerKey="3" />
複製程式碼

此處在一個頁面中引用了三個相同的元件,有一個multireducerKey是必須的,用於區分元件。(這和React在處理List等擁有相同資料結構的元件的時候,需要一個key是相同的道理)

處理Rudecer

在進行combineReducers處,需要指出剛才multireducerKey對應的value是指的什麼

export default combineReducers({
  routing: routerReducer,
  reduxAsyncConnect,
  multireducer: multireducer({
    1: XXX,
    2: XXX,
    3: XXX
  })
});
複製程式碼

此處的格式是固定的,XXX代表需要進行隔離處理的元件的Redux,對應的1,2,3就是在步驟3處multireducerKey的值,(note:說的是格式固定,但是其中的引數是可以根據自己的情況進行變化的)

基於如上的4步操作就可以將A元件進行元件隔離操作了。 原理解釋

採用此處的處理方式與第一種處理方式相比,被隔離的元件沒有脫離整個Store樹,而是根據multireducerKey來判斷使用者當前操作傳送的action是來自哪個一個,然後根據multireducerKey進行對應的資料操作處理。


相關文章