JSステップアップ(一)高次関数HOFと高次コンポーネントHOC(Higher Order Func/Comp)
5825 ワード
一、高次関数(コンポーネント)とは何ですか.作用は何ですか.
子クラスが親クラスを使用する方法は継承によって実現できるが、関連コンポーネント通信(redux)、親が子クラスメソッド(逆継承)を使用するのは、クラス(関数)の機能交差/機能多重化などの問題を解決するために、クラス/関数にクラス/関数(継承)を返すようにクラスに独自の未定義の方法を持たせる.
例えば、
二、高次関数による二つの無関係関数の通信を実現する
需要説明
データ
子はsub、親はsup
ファイルディレクトリ
次に
クラスの
しかし、継承方式を単純に使うと多くのトラブルを引き起こす.たとえば、子クラスと親クラスに同じ名前のメソッドがある場合、デフォルトの子クラスはベースクラス(親クラスの他の呼び方)の同じ名前のメソッドを上書きします.ベースクラスメソッドが関数バインドまたは矢印関数を使用している場合、
そのため、高次コンポーネントによって実現する必要があります.
まず、サブクラス
次に、親1
同様に
このような基礎的な簡単なコンポーネント通信が完了しました.
この考え方によって、グローバル変数のようなStore.jsをカプセル化することができます.
問題を考える
まず
メソッド内でクラスのデータを使用している場合、私は矢印関数を使用していることがわかります.矢印関数
我々は実行する
ブラウザが直接エラーを報告していることがわかります:Cannot use'in'operator to search for'name'in undefined
問題点を特定します(
これで
---後述
React HOC
子クラスが親クラスを使用する方法は継承によって実現できるが、関連コンポーネント通信(redux)、親が子クラスメソッド(逆継承)を使用するのは、クラス(関数)の機能交差/機能多重化などの問題を解決するために、クラス/関数にクラス/関数(継承)を返すようにクラスに独自の未定義の方法を持たせる.
例えば、
react-redux
のconnectメソッドでは、高次コンポーネントが使用されます.React Redux
の接続:const HOC = connnect(mapStateToProps)(Comp);
// connect =>
function connect(mapStateToProps) {
// ...
return function(Comp) {
// ...
}
}
//
const connect = mapStateToProps => Comp => {...};
二、高次関数による二つの無関係関数の通信を実現する
需要説明
データ
SubClass
オブジェクトがあり、state
の2つの関数メソッドがあるクラスsetState getState
(サブクラス)が存在する.SupClass1
(スーパー/親1)でSubClass
(子)のsetState
メソッドを呼び出し、SupClass2
(スーパー/親2)でgetState
メソッドで結果を出力することが望ましい.子はsub、親はsup
ファイルディレクトリ
├ ├── SubClass.js #
├ ├── SupClass1.js # 1
├ ├── SupClass2.js # 2
├── index.html
SubClass
クラスにデータstateを追加し、クエリーと変更の能力を付与// SubClass.js
class SubClass {
constructor(args = {}) {
this.state = {
...args,
};
}
//
setState = (key, val) => {
this.state = {
[key]: val,
};
};
getState = (key) => {
if (key in this.state) {
return this.state[key];
}
//
const err = ' key ';
throw err;
};
}
SubClass
の機能を試してみましょう// index.html
const subcls = new SubClass({name: 'xiaobe'});
const res = subCls.getState('name');
console.log('res', res);
// xiaobe,
次に
SupClass1
にsetState
の能力を与えますclass SuperClass1 {
set(key, val) {
// SuperClass1 setState !
this.setState(key, val);
}
}
クラスの
get
メソッドを直接実行すると、エラーが発生するに違いありません.SupClass1
に何かをする必要がありますSuperClass1
クラスにメソッドsetState
を追加する必要があります.継承を使用できます.// SuperClass1.js
class SuperClass1 extends SubClass {
constructor(props) {
super(props);
}
set(key, val) {
// 1 setState
this.setState(key, val);
}
}
// index.html
const supCls1 = new SuperClass1({name: 'sup-xiaobe'});
const res = supCls1.getState('name');
console.log(res);
// sup-xiaobe
しかし、継承方式を単純に使うと多くのトラブルを引き起こす.たとえば、子クラスと親クラスに同じ名前のメソッドがある場合、デフォルトの子クラスはベースクラス(親クラスの他の呼び方)の同じ名前のメソッドを上書きします.ベースクラスメソッドが関数バインドまたは矢印関数を使用している場合、
this
の指向が変更され、ベースクラスを指し、独自の同じ名前のメソッドが無効になります.そのため、高次コンポーネントによって実現する必要があります.
まず、サブクラス
SubClass
にHOCエントリを追加します.class SubClass {
// ...
HOC(cls) {
// SubClass , this
const sub_this = this;
// , !
return class extends cls {
constructor(props) {
super(props);
// this ,sub_this SubClass
this.getState = sub_this.getState;
this.setState = sub_this.setState;
}
}
}
// ...
}
次に、親1
SupClass1
をインスタンス化する前にアップグレードします(HOCを呼び出します).// index.html
const subCls = new SubClass();
// HOC
const supClsHoc1 = subCls.HOC(SuperClass1);
//
const supCls1 = new supClsHoc1();
// state.name
supCls1.set('name', 'sup-xiaobe');
console.log(supCls.getState('name'));
// sup-xiaobe
同様に
SupClass2
を完了// SupClass2.js
class SuperClass2 {
get(key) {
return this.getState(key);
}
}
// index.html
const subCls = new SubClass({name: 'xiaobe'});
const supClsHoc1 = subCls.HOC(SuperClass1);
const supClsHoc2 = subCls.HOC(SuperClass2);
const supCls1 = new supClsHoc1();
const supCls2 = new supClsHoc2();
supCls1.set('name', 'sup-xiaobe');
const res = supCls2.get('name');
console.log('res', res);
このような基礎的な簡単なコンポーネント通信が完了しました.
この考え方によって、グローバル変数のようなStore.jsをカプセル化することができます.
問題を考える
getState setState this ?
まず
SubClass
の完全なコードを列挙しますclass SubClass {
constructor(args = {}) {
this.state = {
...args,
};
}
// !
setState = (key, val) => {
this.state = {
[key]: val,
};
};
// !
getState = (key) => {
if (key in this.state) {
return this.state[key];
}
return "";
};
HOC(cls) {
const sub_this = this;
return class extends cls {
constructor(props) {
super(props);
// this ,sub_this SubClass
this.getState = sub_this.getState;
this.setState = sub_this.setState;
}
}
}
}
メソッド内でクラスのデータを使用している場合、私は矢印関数を使用していることがわかります.矢印関数
this
を使用しないと、どのような問題が発生するか考えてみましょう.getState(key) {
// ...
}
我々は実行する
const subCls = new SubClass({name: 'xiaobe'});
const supClsHoc2 = subCls.HOC(SuperClass2);
const supCls2 = new supClsHoc2();
console.log('supCls2', supCls2.get('name'));
ブラウザが直接エラーを報告していることがわかります:Cannot use'in'operator to search for'name'in undefined
SuperClass2
類にはstate
は存在しないからです!言い換えればthis.state = undefined
であり、undefined
で対象メソッドを使用すると、当然エラーが発生する.問題点を特定します(
SubClass
クラスのデータ/メソッドが必要です).次のいくつかの解決策があります.// 1. HOC state
this.state = sub_this.state;
// 2.getState , this SubClass
getState = key => { ... };
// 3. getState this SubClass
this.getState = sub_this.getState.bind(sub_this);
これで
this
の誤った問題が解決しました.this
の全面的な解析について、私のこの文章を見てください.---後述
React HOC