『譯』React Mixin 的使用

dmc3 9年前發布 | 28K 次閱讀 React 移動Web開發框架 移動開發

我使用React.js構建大型項目已經有一段時間了,我遇到過很多在不同的組件中都要用到相同功能的情況。因此,我花了一個小時左右的時間去了解mixin的用法,然后分享我所學習到的一些東西。

為什么使用 Mixin ?

React回避子類組件,但是我們知道,到處重復地編寫同樣的代碼是不好的。所以為了將同樣的功能添加到多個組件當中,你需要將這些通用的功能包裝成一個mixin,然后導入到你的模塊中。 可以說,相比繼承而已,React更喜歡這種組合的方式。嗯,我也喜歡這樣。

寫一個簡單的 Mixin

現在假設我們在寫一個app,我們知道在某些情況下我們需要在好幾個組件當中設置默認的name屬性。

現在,我們不再是像以前一樣在每個組件中寫多個同樣的getDefaultProps方法,我們可以像下面一樣定義一個mixin:

</div>

javascriptvar DefaultNameMixin = {
    getDefaultProps: function () {
        return {name: "Skippy"};
    }
};

它沒什么特殊的,就是一個簡單的對象而已。

加入到 React 組件中

為了使用mixin,我們只需要簡單得在組件中加入mixins屬性,然后把剛才我們寫的mixin包裹成一個數組,將它作為該屬性的值即可:

javascriptvar ComponentOne = React.createClass({
    mixins: [DefaultNameMixin],
    render: function() {
        return 
<h2>Hello {this.props.name}</h2>
;
    }
});
React.renderComponent(<ComponentOne />, document.body);

JSFiddle 示例:一個簡單的 mixin 例子

重復使用

就像你想象的那樣,我們可以在任何其他組件中包含我們的mixin:

javascriptvar ComponentTwo = React.createClass({
    mixins: [DefaultNameMixin],
    render: function () {
        return (
            <div>
                <h4>{this.props.name}</h4>
                <p>Favorite food: {this.props.food}</p>
            </div>
        );
    }
});

JSFiddle 示例:在多個組件中使用同一個 mixin

生命周期方法會被重復調用!

如何你的mixin當中包含 生命周期方法 ,不要焦急,你仍然可以在你的組件中使用這些方法,而且它們都會被調用:

JSFiddle 示例:展示了兩個 default props 都會被設置

兩個getDefaultProps方法都將被調用,所以我們可以得到默認為Skippy的name屬性和默認為Pancakes的food屬性。任何一個生命周期方法或屬性都會被順利地重復調用,但是下面的情況除外:

  • render:包含多個render方法是不行的。React 會跑出異常:
  • </ul>

    plainUncaught Error: Invariant Violation: ReactCompositeComponentInterface: 
    You are attempting to define `render` on your component more than once. 
    This conflict may be due to a mixin.

    • displayName:你多次的對它進行設置是沒有問題的,但是,最終的結果只以最后一次設置為準。
    • </ul>

      需要指出的是,mixin是可以包含在其他的mixin中的:

      javascriptvar UselessMixin = {
           componentDidMount: function () {
              console.log("asdas");
           }
      };
      var LolMixin = {
          mixins: [UselessMixin]
      };
      var PantsOpinion = React.createClass({
          mixins: [LolMixin],
          render: function () {
               return (
      <p>I dislike pants</p>
      );
          }
      });
      React.renderComponent(<PantsOpinion />, document.body);

      程序會在控制臺打印出asdas。

      包含多個 Mixins

      我們的mixins要包裹在數組當中,提醒了我們可以在組件中包含多個mixins:

      javascriptvar DefaultNameMixin = {
          getDefaultProps: function () {
              return {name: "Lizie"};
          }
      };
      var DefaultFoodMixin = {
          getDefaultProps: function () {
              return {food: "Pancakes"};
          }
      };
      var ComponentTwo = React.createClass({
          mixins: [DefaultNameMixin, DefaultFoodMixin],
          render: function () {
              return (
      <div>
                      <h4>{this.props.name}</h4>
                      <p>Favorite food: {this.props.food}</p>
                  </div>
              );
          }
      });

      注意事項

      這里有幾件事需要引起我們的注意,當我們使用mixins的時候。 幸運地是,這些看起來并不是什么大問題,下面是我們在實踐當中發現的一些問題:

      設置相同的 Prop 和 State

      如果你嘗試在不同的地方定義相同的屬性時會出現下面的異常:

      plainUncaught Error: Invariant Violation: mergeObjectsWithNoDuplicateKeys(): 
      Tried to merge two objects with the same key: name

      設置相同的方法

      在不同的mixin中定義相同的方法,或者mixin和組件中包含了相同的方法時,會拋出異常:

      javascriptvar LogOnMountMixin = {
          componentDidMount: function () {
              console.log("mixin mount method");
              this.logBlah()
          },
          // add a logBlah method here...
          logBlah: function () {
              console.log("blah");
          }
      };
      var MoreLogOnMountMixin = {
          componentDidMount: function () {
              console.log("another mixin mount method");
          },
          // ... and again here.
          logBlah: function () {
              console.log("something other than blah");
          }
      };

      異常信息同多次定義rander方法時拋出的異常一樣:

      plainUncaught Error: Invariant Violation: ReactCompositeComponentInterface: 
      You are attempting to define `logBlah` on your component more than once. 
      This conflict may be due to a mixin.

      多個生命周期方法的調用順序

      如果我們的組件和mixin中都包含了相同的生命周期方法的話會怎樣呢?

      我們的mixin方法首先會被調用,然后再是組件的中方法被調用。

      </div>

      那當我們的組件中包含多個mixin,而這些mixin中又包含相同的生命周期方法時,調用順序又是如何?

      它們會根據mixins中的順序從左到右的進行調用。

      </div>

      實例代碼:

      javascriptvar LogOnMountMixin = {
          componentDidMount: function () {
              console.log("mixin mount method");
          }
      };
      var MoreLogOnMountMixin = {
          componentDidMount: function () {
              console.log("another mixin mount method");
          }
      };
      var ComponentOne = React.createClass({
          mixins: [MoreLogOnMountMixin, LogOnMountMixin],
          componentDidMount: function () {
              console.log("component one mount method");
          },
          ...
      var ComponentTwo = React.createClass({
          mixins: [LogOnMountMixin, MoreLogOnMountMixin],
          componentDidMount: function () {
              console.log("component two mount method");
          },
          ...

      控制臺將輸出:

      plainanother mixin mount method
      mixin mount method 
      component one mount method

      mixin mount method another mixin mount method component two mount method</pre>

      總結

      Mixin 使你React程序變得更為可重用,It's a Good Thing.

      我希望這篇文章能夠對你有所幫助,如果有任何反饋,很高興你能夠在推ter上 @veddermatic

      </div>

      原文鏈接: http://simblestudios.com/blog/development/react-mixins-by-example.html

      翻譯水平有限,文中帶有個人理解,如有不恰當的地方,請在評論中指出,非常感謝!

      </div> </div> 原文 http://segmentfault.com/a/1190000003016446

       本文由用戶 dmc3 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
       轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
       本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!