国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

精益 React 學習指南 (Lean React)- 4.2 react patterns

Berwin / 1109人閱讀

摘要:另外一點是組件應該盡量保證獨立性,避免和外部的耦合,使用全局事件造成了和外部事件的耦合。明確的職責分配也增加了應用的確定性明確只有組件能夠知道狀態數據,且是對應部分的數據。

書籍完整目錄

4.2 react patterns

修改 Props

Immutable data representation

確定性

在 getInitialState 中使用 props

私有狀態和全局事件

render 包含 side effects

jQuery 修改 DOM

使用無狀態組件

內存管理

componentWillUnmount 取消訂閱事件

判斷 isMounted

上層設計

使用 container component

使用 Composition 替代 mixins

Composability - Presenter Pattern

Composability - Decorator Pattern

Context 數據傳遞

4.2.1 關于

React 的框架設計是趨于函數式的,其中最主要的兩點也是為什么會選擇 React 的兩點:

單向性:數據的流動是單向的

確定性:React(storeData) = view 相同數據總是渲染出相同的 view

這兩點即是特性也是設計 React 應用的基本原則,圍繞這兩個原則社區里邊出現了一些 React 設計模式,即有好的設計模式也有應該要避免的反模式,理解這些設計模式能夠幫助我們寫出更優質的 React 應用,本節將圍繞 單向性、確定性、內存管理、上層設計 來討論這些設計模式。

anti 表示反模式,good 表示好模式

4.2.2 單向性

數據的流動是單向的

修改 Props (anti)

描述: 組件任何地方修改 props 的值

解釋:

React 的數據流動是單向性的,流動的方式是通過 props 傳遞到組件中,而在 Javascript 中對象是通過引用傳遞的,修改 props 等于直接修改了 store 中的數據,導致破壞數據的單向流動特性

使用不可變數據 (good)

描述: store data 使用不可變數據

解釋: Javascript 對象的特性是可以任意修改,而這個特性很容易破壞數據的單向性,因為人工無法永遠確保數據沒有被修改過,唯一的做法是使用不可變數據,用代碼邏輯確保數據不能被任意修改,后面會有一個完整的小節介紹不可變數據在 React 中的應用

4.2.3 確定性

React(storeData) = view 相同數據總是渲染出相同的 view

在 getInitialState 中使用 props (anti)

描述: getInitialState 通過 props 來生成 state 數據

解釋:

官方文檔 https://facebook.github.io/react/tips/props-in-getInitialState-as-anti-pattern.html

在 getInitialState 中通過 props 來計算 state 破壞了確定性原則,“source of truth” 應該只是來自于一個地方,通過計算 state 過后增加了 truth source。這種做法的另外一個壞處是在組件更新的時候,還需要計算重新計算這部分 state。

舉例:

var MessageBox = React.createClass({
  getInitialState: function() {
    return {nameWithQualifier: "Mr. " + this.props.name};
  },

  render: function() {
    return 
{this.state.nameWithQualifier}
; } }); ReactDOM.render(, mountNode);

優化方式:

var MessageBox = React.createClass({
  render: function() {
    return 
{"Mr. " + this.props.name}
; } }); ReactDOM.render(, mountNode);

需要注意的是以下這種做法并不會影響確定性

var Counter = React.createClass({
  getInitialState: function() {
    // naming it initialX clearly indicates that the only purpose
    // of the passed down prop is to initialize something internally
    return {count: this.props.initialCount};
  },

  handleClick: function() {
    this.setState({count: this.state.count + 1});
  },

  render: function() {
    return 
{this.state.count}
; } }); ReactDOM.render(, mountNode);
私有狀態和全局事件 (anti)

描述: 在組件中定義私有的狀態或者使用全局事件

介紹: 組件中定義了私有狀態和全局事件過后,組件的渲染可能會出現不一致,因為全局事件和私有狀態都可以控制組件的狀態,這樣外部使用組件無法保證組件的渲染結果,影響了組件的確定性。另外一點是組件應該盡量保證獨立性,避免和外部的耦合,使用全局事件造成了和外部事件的耦合。

render 函數包含 side effects (anti)

side effect 解釋: https://en.wikipedia.org/wiki/Side_effect_(computer_science)

描述: render 函數包含一些 side effects 的代碼邏輯,這些邏輯包括如

修改 state 數據

修改 props 數據

修改全局變量

調用其他導致 side effect 的函數

解釋: render 函數如果包含了 side effect ,渲染的結果不再可信,所以確保 render 函數為純函數

jQuery 修改 DOM (anti)

描述: 使用外部 DOM 框架修改或刪除了 DOM 節點、屬性、樣式
解釋: React 中 DOM 的結構和屬性都是由渲染函數確定的,如果使用了 Jquery 修改 DOM,那么可能造成沖突,視圖的修改源頭增加,直接影響組件的確定性

使用無狀態組件 (good)

描述: 優先使用無狀態組件
解釋: 無狀態組件更符合函數式的特性,如果組件不需要額外的控制,只是渲染結構,那么應該優先選擇無狀態組件

4.2.4 內存管理 componentWillUnmount 取消訂閱事件 (good)

描述: 如果組件需要注冊訂閱事件,可以在 componentDidMount 中注冊,且必須在 ComponentWillUnmount 中取消訂閱
解釋: 在組件 unmount 后如果沒有取消訂閱事件,訂閱事件可能仍然擁有組件實例的引用,這樣第一是組件內存無法釋放,第二是引起不必要的錯誤

判斷 isMounted (anti)

描述: 在組件中使用 isMounted 方法判斷組件是否未被注銷
解釋:

React 中在一個組件 ummount 過后使用 setState 會出現warning提示(通常出現在一些事件注冊回調函數中) ,避免 warning 的解決辦法是:

if(this.isMounted()) { // This is bad.
  this.setState({...});
}

但這是個掩耳盜鈴的做法,因為如果出現了錯誤提示就表示在組件 unmount 的時候還有組件的引用,這個時候應該是已經導致了內存溢出。所以解決錯誤的正確方法是在 componentWillUnmount 函數中取消監聽:

class MyComponent extends React.Component {
  componentDidMount() {
    mydatastore.subscribe(this);
  }
  render() {
    ...
  }
  componentWillUnmount() {
    mydatastore.unsubscribe(this);
  }
}
4.2.5 上層設計 使用 container component (good)

描述: 將 React 組件分為兩類 container 、normal ,container 組件負責獲取狀態數據,然后傳遞給與之對應的 normal component,對應表示兩個組件的名稱對應,舉例:

TodoListContainer => TodoList
FooterContainer => Footer

解釋: 參看 redux 設計中的 container 組件,container 組件是 smart 組件,normal 組件是 dummy 組件,這樣的責任分離讓 normal 組件更加獨立,不需要知道狀態數據。明確的職責分配也增加了應用的確定性(明確只有 container 組件能夠知道狀態數據,且是對應部分的數據)。

使用 Composition 替代 mixins (good)

描述: 使用組件的組合的方式(高階組件)替代 mixins 實現為組件增加附加功能
解釋:

mixins 的設計主要目的是給組件提供插件機制,大多數情況使用 mixin 是為了給組件增加額外的狀態。但是使用 mixins 會帶來一些額外的壞處:

mixins 通常需要依賴組件定義特定的方法,如 getSomeMixinState ,而這個是隱式的約束

多個 mixins 可能會導致沖突

mixins 通常增加了額外的狀態數據,而 react 的設計應該是要避免過多的內部狀態

mixins 可能會影響 shouldComponentUpdate 的邏輯, mixins 做了很多數據合并的邏輯

另外一點是在新版本的 React 中,mixins 將會是廢棄的 feature,在 es6 class 定義組件也不會支持 mixins。

舉個例子,一個訂閱 fluxstore 的 mixin 為:

function StoreMixin(store) {
  var Mixin = {
    getInitialState() {
      return this.getStateFromStore(this.props);
    },
    componentDidMount() {
      store.addChangeListener(this.handleStoreChanged)
      this.setState(this.getStateFromStore(this.props));
    },
    componentWillUnmount() {
      store.removeChangeListener(this.handleStoreChanged)
    },
    handleStoreChanged() {
      if (this.isMounted()) {
        this.setState(this.getStateFromStore(this.props));
      }
    }
  };
  return Mixin;
}

使用

const TodolistContainer = React.createClass({
  mixins: [StoreMixin(AppStore)],
  getStateFromStore(props) {
    return {
      todos: AppStore.get("todos");
    }
  }
})

轉換為組件的組合方式為:

function connectToStores(Component, store, getStateFromStore) {
  const StoreConnection = React.createClass({
    getInitialState() {
      return getStateFromStore(this.props);
    },
    componentDidMount() {
        store.addChangeListener(this.handleStoreChanged)
    },
    componentWillUnmount() {
        store.removeChangeListener(this.handleStoreChanged)
    },
    handleStoreChanged() {
      if (this.isMounted()) {
        this.setState(getStateFromStore(this.props));
      }
    },
    render() {
      return ;
    }
  });
  return StoreConnection;
};

使用方式:

class Todolist extends React.Component {
    render() {
        // ....
    }
}
TodolistContainer = connectToStore(Todolist, AppStore, props => {
    todos: AppStore.get("todos")
})
Presenter Pattern

描述: 利用 children 可以作為函數的特性,將數據獲取和數據表現分離成為兩個不同的組件

如下例子:

class DataGetter extends React.Component {
  render() {
    const { children } = this.props
    const data = [ 1,2,3,4,5 ]
    return children(data)
  }
}

class DataPresenter extends React.Component {
  render() {
    return (
      
        {data =>
          
    {data.map((datum) => (
  • {datum}
  • ))}
}
) } } const App = React.createClass({ render() { return ( ) } })

解釋: 將數據獲取和數據展現分離,同時利用組件的 children 可以作為函數的特性,讓數據獲取和數據展現都可以作為組件使用

Decorator Pattern

描述: 父組件通過 cloneElement 方法給子組件添加方法和屬性

cloneElement 方法:

ReactElement cloneElement(
  ReactElement element,
  [object props],
  [children ...]
)

如下例子:

const CleverParent = React.createClass({
  render() {
    const children = React.Children.map(this.props.children, (child) => {
      return React.cloneElement(child, {
        // 新增 onClick 屬性
        onClick: () => alert(JSON.stringify(child.props, 0, 2))
      })
    })
    return 
{children}
} }) const SimpleChild = React.createClass({ render() { return (
{this.props.children}
) } }) const App = React.createClass({ render() { return ( 1 2 ) } })

解釋: 通過這種設計模式,可以應用到一些自定義的組件設計,提供更簡潔的 API 給第三方使用,如 facebook 的 FixedDataTable 也是應用了這種設計模式

Context 數據傳遞

描述: 通過 Context 可以讓所有組件共享相同的上下文,避免數據的逐級傳遞, Context 是大多數 flux 庫共享 store 的基本方法。

使用方法:

/**
 * 初始化定義 Context 的組件
 */
class Chan extends React.Component {
  getChildContext() {
    return {
      environment: "grandma"s house"
    }
  }
}

// 設置 context 類型
Chan.childContextTypes = {
  environment: React.PropTypes.string
};

/**
 * 子組件獲取 context 
 */
class ChildChan extends React.Component {
  render() {
    const ev = this.context.environment;
  }
}
/**
 * 需要設置 contextTypes 才能獲取
 */
ChildChan.contextTypes = {
  environment: React.PropTypes.string
};

解釋: 通常情況下 Context 是為基礎組件提供的功能,一般情況應該避免使用,否則濫用 Context 會影響應用的確定性。

參考鏈接

https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750#.hvbsii4zd

http://www.zhubert.com/blog/2016/02/05/react-composability-patterns/

https://medium.com/@learnreact/context-f932a9abab0e#.wn00ktlde

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/79819.html

相關文章

  • 精益 React 學習指南Lean React)- 4.1 react 代碼規范

    書籍完整目錄 4.1 react 代碼規范 showImg(https://segmentfault.com/img/bVyE9m); 關于 基礎規范 組件結構 命名規范 jsx 書寫規范 eslint-plugin-react 關于 在代碼的設計上,每個團隊可能都有一定的代碼規范和模式,好的代碼規范能夠提高代碼的可讀性便于協作溝通,好的模式能夠上層設計上避免不必要的 bug 出現。本節會參考...

    zhangqh 評論0 收藏0
  • 精益 React 學習指南Lean React)- 1.2 JSX 語法

    摘要:需要提醒讀者的是,的很多例子都是通過來寫的,但這并不是語法,后面我們會有單獨的一小節講解的基本語法,不過目前為止我們先將跟多精力放在上。 書籍完整目錄 1.2 JSX 語法 showImg(https://segmentfault.com/img/bVvKLR); 官方文檔 https://facebook.github.io/react/docs/jsx-in-depth.html ...

    moven_j 評論0 收藏0
  • 精益 React 學習指南Lean React)- 1.1 React 介紹

    摘要:單向數據流應用的核心設計模式,數據流向自頂向下我也是性子急的人,按照技術界的慣例,在學習一個技術前,首先得說一句。然而的單向數據流的設計讓前端定位變得簡單,頁面的和數據的對應是唯一的我們可以通過定位數據變化就可以定位頁面展現問題。 書籍完整目錄 1.1 React 介紹 showImg(https://segmentfault.com/img/bVvJgS); 1.1.1 React ...

    lsxiao 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<