この記事では主にreactの全体的なプロセスを紹介します
リストの差分アルゴリズムは少し異なります。リストは通常、同じ構造を持っているため、リスト ノードを削除、挿入、並べ替える場合、単一ノードの全体的な操作は、各置換を 1 つずつ比較するよりもはるかに優れています。リストの場合、react が誰が誰であるかを認識できるようにキー値を設定する必要があります。もちろん、キー値を書き込まなくても問題ありませんが、これにより通常は警告が表示され、react のパフォーマンスを向上させるためにキー値を追加するよう通知されます。
2 つの記述メソッドは同じ機能を実現しますが、原則が異なります。es6 クラスのクラスはコンストラクターの構文糖とみなされ、extends が実装されます。クラス間の継承 - React.Component のすべてのプロパティとメソッドを継承するクラス Main を定義します。これがコンポーネントのライフサイクル関数の由来です。コンストラクターは、オブジェクトをインスタンス化するときに呼び出されるコンストラクターです。Super は、親クラスのコンストラクターを呼び出して親クラスのインスタンス オブジェクトを作成し、サブクラスのコンストラクターを使用してそれを変更します。これは、es5 のプロトタイプ継承とは異なります。プロトタイプ継承では、まずインスタンス化されたオブジェクトが作成され、次に親のプロトタイプ メソッドが継承されます。これを理解すると、コンポーネントを見るときがより明確になります。 コンポーネント を使用すると、実際には Main クラス (new Main) のインスタンス化になりますが、react はこのプロセスをカプセル化してラベルのように見せます。 (さらに詳しく知りたい場合は、PHP 中国語 Web サイトコンポーネントのライフサイクルReact Reference Manual のコラムにアクセスして学習してください)
注意すべき点が 3 つあります: 1. 定義されたクラス名の最初の文字は大文字にする必要があります。 2. クラスにはキーワードになる場合、クラス セレクターには代わりに className を使用する必要があります。 3. クラスとモジュールはデフォルトで strict モードを使用するため、use strict で実行モードを指定する必要はありません。
コンポーネントは、初期化中に 5 つのフック関数をトリガーします:
1、getDefaultProps()
デフォルトのプロパティを設定する dufaultProps を使用してコンポーネントのデフォルトのプロパティを設定することもできます。
2. getInitialState()
es6 クラス構文を使用する場合、コンストラクターで this.state を直接定義できます。 this.props にアクセスできるようになりました。
3.componentWillMount()
は、コンポーネントが初期化されるときにのみ呼び出されます。このとき、コンポーネントが更新されるときは呼び出されません。変更することができます。
4. render()
React の最も重要なステップ、仮想 dom の作成、diff アルゴリズムの実行、dom ツリーの更新はすべてここで行われます。この時点では、状態を変更することはできません。
5. コンポーネントがレンダリングされた後に、componentDidMount()
が呼び出されます。これは、一度だけ呼び出されます。
は、更新時に 5 つのフック関数もトリガーします:
6、componentWillReceivePorps(nextProps)
これは、コンポーネントの初期化時には呼び出されませんが、コンポーネントが新しい props を受け入れるときに呼び出されます。
7. shouldComponentUpdate(nextProps, nextState)
反応パフォーマンスの最適化の非常に重要な部分です。コンポーネントが新しい状態またはプロパティを受け入れるときに呼び出されます。比較の前後の 2 つのプロパティと状態が同じであるかどうかを設定できます。同じ属性の状態は確実に同じものを生成するため、更新を防ぐために false を返します。 DOM ツリーなので、新しい DOM ツリーを作成し、古い DOM ツリーを diff アルゴリズムと比較する必要はありません。これにより、特に DOM 構造が複雑な場合に、パフォーマンスが大幅に節約されます。ただし、this.forceUpdate を呼び出すと、この手順はスキップされます。いいえ、もっと言います
10. コンポーネントの初期化時には、componentDidUpdate()
は呼び出されません。このとき、コンポーネントの更新が完了した後に呼び出されます。
アンインストールフック機能もあります 11. コンポーネントがアンマウントされる直前に、componentWillUnmount() が呼び出されます。この時点で、一部のイベント リスナーとタイマーをクリアする必要があります。 上記のことから、React には合計 10 個の周期関数 (レンダリングは 1 回繰り返されます) があることがわかります。これらの 10 個の関数は、うまく使用すると、開発効率とコンポーネントのパフォーマンスを向上させることができます。 。 Router と Route は React のコンポーネントであり、内部ルーティング ルールを作成し、一致するルーティング アドレスに従って対応するコンポーネントを表示するだけの設定オブジェクトです。 Route にはルーティング アドレスとコンポーネントをバインドするネスト機能があり、ルーティング アドレスの包含関係を示します。これはコンポーネント間のネストとは直接関係しません。 Route はバインドされたコンポーネントに 7 つの属性 (children、history、location、params、route、routeParams、routes) を渡すことができます。各属性にはルーティング関連の情報が含まれます。よく使われるのは、子(ルーティングの包含関係で区別される構成要素)、ロケーション(アドレス、パラメータ、アドレス切り替え方式、キー値、ハッシュ値を含む)です。 act-router は、a タグをカプセル化した Link タグを提供します。react-router は、リンクをクリックしてジャンプすることをデフォルトの方法ではなく、pushState を使用してジャンプします。ハッシュ値を変更します。ページを切り替えるプロセスでは、[リンク] ラベルまたは [戻る] ボタンをクリックすると、最初に URL アドレスが変更され、ルーターはアドレスの変更を監視し、ルートのパス属性に従って対応するコンポーネントと照合して状態を変更します。 value を対応するコンポーネントに渡し、setState を呼び出すと、render 関数がトリガーされて dom が再レンダリングされます。 ページ数が多い場合、特に単一ページのアプリケーションでは、初期のレンダリング速度が非常に遅くなり、オンデマンドでロードする必要があります。ページに切り替えるときに、対応する js ファイルを読み込みます。 webpackでロードオンデマンドに反応する方法は非常に簡単で、RouteのコンポーネントをgetComponentに変更し、require.ensureでコンポーネントを取得し、webpackにchunkFilenameを設定します。 React は上から下にデータを転送する一方向のデータ フローを推奨しますが、ボトムアップ間の通信や、同じデータ フロー上にないコンポーネント間の通信は複雑になります。通信の問題を解決するには、親子関係のみがある場合、親がコールバック関数を属性として子に渡し、子がその関数を直接呼び出して親と通信することができます。 コンポーネント レベルが深くネストされている場合、Context を使用して情報を渡すことができます。これにより、層ごとに関数を渡す必要がなく、this.context を通じてどのレベルの子にも直接アクセスできます。 兄弟関係にあるコンポーネントは相互に直接通信できません。転送ステーションとしては同じ層の上位のみを使用できます。兄弟コンポーネントが最上位コンポーネントである場合、それらが通信できるようにするには、その外側のコンポーネントがデータを保存し、情報を送信する役割を果たします。これが実際の redux です。物事をします。 コンポーネント間の情報は、グローバル イベントを通じて渡すこともできます。別のページではパラメーターを介してデータを渡すことができ、次のページでは location.query を使用してデータを取得できます。 store はオブジェクトであり、次の 4 つの主要なメソッドがあります: 1. 用于action的分发——在createStore中可以用middleware中间件对dispatch进行改造,比如当action传入dispatch会立即触发reducer,有些时候我们不希望它立即触发,而是等待异步操作完成之后再触发,这时候用redux-thunk对dispatch进行改造,以前只能传入一个对象,改造完成后可以传入一个函数,在这个函数里我们手动dispatch一个action对象,这个过程是可控的,就实现了异步。 2、subscribe: 监听state的变化——这个函数在store调用dispatch时会注册一个listener监听state变化,当我们需要知道state是否变化时可以调用,它返回一个函数,调用这个返回的函数可以注销监听。 3、getState: 获取store中的state——当我们用action触发reducer改变了state时,需要再拿到新的state里的数据,毕竟数据才是我们想要的。getState主要在两个地方需要用到,一是在dispatch拿到action后store需要用它来获取state里的数据,并把这个数据传给reducer,这个过程是自动执行的,二是在我们利用subscribe监听到state发生变化后调用它来获取新的state数据,如果做到这一步,说明我们已经成功了。 4、replaceReducer: 替换reducer,改变state修改的逻辑。 store可以通过createStore()方法创建,接受三个参数,经过combineReducers合并的reducer和state的初始状态以及改变dispatch的中间件,后两个参数并不是必须的。store的主要作用是将action和reducer联系起来并改变state。 action是一个对象,其中type属性是必须的,同时可以传入一些数据。action可以用actionCreactor进行创造。dispatch就是把action对象发送出去。 reducer是一个函数,它接受一个state和一个action,根据action的type返回一个新的state。根据业务逻辑可以分为很多个reducer,然后通过combineReducers将它们合并,state树中有很多对象,每个state对象对应一个reducer,state对象的名字可以在合并时定义。 像这个样子: combineReducers其实也是一个reducer,它接受整个state和一个action,然后将整个state拆分发送给对应的reducer进行处理,所有的reducer会收到相同的action,不过它们会根据action的type进行判断,有这个type就进行处理然后返回新的state,没有就返回默认值,然后这些分散的state又会整合在一起返回一个新的state树。 接下来分析一下整体的流程,首先调用store.dispatch将action作为参数传入,同时用getState获取当前的状态树state并注册subscribe的listener监听state变化,再调用combineReducers并将获取的state和action传入。combineReducers会将传入的state和action传给所有reducer,reducer会根据state的key值获取与自己对应的state,并根据action的type返回新的state,触发state树的更新,我们调用subscribe监听到state发生变化后用getState获取新的state数据。 redux的state和react的state两者完全没有关系,除了名字一样。 上面分析了redux的主要功能,那么react-redux到底做了什么? 如果只使用redux,那么流程是这样的: component --> dispatch(action) --> reducer --> subscribe --> getState --> component 用了react-redux之后流程是这样的: component --> actionCreator(data) --> reducer --> component store的三大功能:dispatch,subscribe,getState都不需要手动来写了。react-redux帮我们做了这些,同时它提供了两个好基友Provider和connect。 Provider是一个组件,它接受store作为props,然后通过context往下传,这样react中任何组件都可以通过contex获取store。也就意味着我们可以在任何一个组件里利用dispatch(action)来触发reducer改变state,并用subscribe监听state的变化,然后用getState获取变化后的值。但是并不推荐这样做,它会让数据流变的混乱,过度的耦合也会影响组件的复用,维护起来也更麻烦。 connect --connect(mapStateToProps, mapDispatchToProps, mergeProps, options)是一个函数,它接受四个参数并且再返回一个函数--wrapWithConnect,wrapWithConnect接受一个组件作为参数wrapWithConnect(component),它内部定义一个新组件Connect(容器组件)并将传入的组件(ui组件)作为Connect的子组件然后return出去。 所以它的完整写法是这样的:connect(mapStateToProps, mapDispatchToProps, mergeProps, options)(component) mapStateToProps(state, [ownProps]): mapStateToProps 接受两个参数,store的state和自定义的props,并返回一个新的对象,这个对象会作为props的一部分传入ui组件。我们可以根据组件所需要的数据自定义返回一个对象。ownProps的变化也会触发mapStateToProps mapDispatchToProps(dispatch, [ownProps]): mapDispatchToProps如果是对象,那么会和store绑定作为props的一部分传入ui组件。如果是个函数,它接受两个参数,bindActionCreators会将action和dispatch绑定并返回一个对象,这个对象会和ownProps一起作为props的一部分传入ui组件。所以不论mapDispatchToProps是对象还是函数,它最终都会返回一个对象,如果是函数,这个对象的key值是可以自定义的 mapDispatchToProps返回的对象其属性其实就是一个个actionCreator,因为已经和dispatch绑定,所以当调用actionCreator时会立即发送action,而不用手动dispatch。ownProps的变化也会触发mapDispatchToProps。 mergeProps(stateProps, dispatchProps, ownProps): mapStateToProps() と mapDispatchToProps() によって返されたオブジェクトとコンポーネント自体の props を新しい props にマージし、コンポーネントに渡します。デフォルトでは、Object.assign({}, ownProps, stateProps,dispatchProps) の結果が返されます。 オプション: pure = true は、Connect コンテナコンポーネントがストアの状態と shouldComponentUpdate 内の ownProps の浅い比較を実行して、変更が発生したかどうかを判断し、パフォーマンスを最適化することを意味します。 false の場合、比較は実行されません。 実際、connect は何も行いません。ほとんどのロジックは、それが返す WrapWithConnect 関数に実装されます。正確には、これは、wrapWithConnect で定義された Connect コンポーネントに実装されます。 1. Provider コンポーネントは redux ストアを props として受け入れ、コンテキストを通じてそれを渡します。 2. connect 関数は、初期化中に mapDispatchToProps オブジェクトをストアにバインドします。mapDispatchToProps が関数の場合、Connect コンポーネントがストアを取得した後、受信した store.dispatch とアクションに従って、bindActionCreators を通じてバインドされます。返されたオブジェクトはストアにバインドされます。connect 関数は、wrapWithConnect 関数を返します。同時に、wrapWithConnect が呼び出され、ui コンポーネントが渡されます。wrapWithConnect は、Connect extends クラスを内部的に使用します。
コンポーネントは Connect コンポーネントを定義します。その後、Connect コンポーネントはコンテキストを通じてストアを取得し、store.getState を通じて完全な状態オブジェクトを取得し、stateProps オブジェクト、mapDispatchToProps を返します。 object または mapDispatchToProps 関数は、dispatchProps オブジェクトを返します。stateProps、dispatchProps、および Connect コンポーネントの props は、Object.assign() または mergeProps を通じて props にマージされ、ui コンポーネントに渡されます。次に、ComponentDidMount で store.subscribe を呼び出し、コールバック関数 handleChange を登録して、状態の変化を監視します。 3. このとき、ui コンポーネントは props 内で actionCreator を見つけることができ、dispatch では自動的に getState が呼び出され、状態全体が取得されます。ストアは状態の変更をリッスンするために登録され、アクションは CombineReducers に渡され、状態のキー値に従ってサブ Reducers にアクションが渡されます。 -reducers。reducers は action.type を判断するために順番に実行され、存在する場合は新しい状態が返され、存在しない場合はデフォルトに戻ります。 combineReducers は、子 Reducer によって返された個々の状態を新しい完全な状態に再度結合します。この時点で状態が変化しました。 Connect コンポーネントで呼び出されるサブスクライブは、状態の変化をリッスンしてから、handleChange 関数を呼び出します。内部的には、handleChange 関数は最初に getState を呼び出して新しい状態の値を取得し、古い状態と新しい状態の浅い比較を実行します。異なる場合は、mapStateToProps を呼び出し、古い状態と新しい状態を簡単に比較します。それらが同じでない場合は、this.setState() を呼び出して Connect コンポーネントの更新をトリガーし、ui コンポーネントを渡して、ui コンポーネントの更新をトリガーします。このとき、ui コンポーネントは新しい props を取得して反応します。
-->redux -->React の 1 回限りのプロセスが終了します。 上記は少し複雑ですが、プロセスの簡略化されたバージョンは次のとおりです: 1. Provider コンポーネントは redux ストアを props として受け入れ、コンテキストを通じてそれを渡します。 2. connect 関数は Provider からストアを受け取り、mapStateToProps、mapDispatchToProps、コンポーネントの 3 つのパラメーターを受け取り、state と actionCreator を props としてコンポーネントに渡します。このとき、コンポーネントは actionCreator 関数を呼び出してリデューサーをトリガーできます。関数を使用して新しい状態を返し、connect で状態の変化を監視し、setState を呼び出してコンポーネントを更新し、新しい状態をコンポーネントに渡します。 Connect は非常に簡潔に記述できます。mapStateToProps と mapDispatchToProps は渡されるコールバック関数です。名前は固定されておらず、名前を記述する必要さえありません。 簡易版: connect(state => state, action)(Component); 上記は、react、react-router、redux に関する知識ポイントです。しかし、それらを統合して完全なプロジェクトを構築する方法は次のとおりです。 1. まず、react.js、redux、react-router などの基本的なファイルを引用します。npm でインストールし、ファイル内で直接引用することをお勧めします。 2.react.js、redux、react-router から必要なオブジェクトとメソッドを導入します。 「react」から React、{Component, PropTypes} をインポートします。 applyMiddleware} from 'redux'; 上の図のトップレベルの ui コンポーネントには合計 18 のプロパティがあります。反応すると、これらのプロパティがどこから来たのか混乱するかもしれません。実際、これらの属性は 5 つの場所から来ます: this.setState() は render メソッドを呼び出しますが、state の値は render メソッドで割り当てられます。したがって、this.setState()実行直後に取得したstateの値は変化しません。レンダー関数が呼び出されないため、同様の状態の直接割り当ては更新をトリガーしません。 2. コンポーネントのライフサイクル 4. リデューサーによって返される状態が変化するかどうかに関係なく、subscribe に登録されているすべてのコールバック関数がトリガーされます。 8、react的路由有hashHistory和browserHistory,hashHistory由hash#控制跳转,一般用于正式线上部署,browserHistory就是普通的地址跳转,一般用于开发阶段。 9、标签里用到的,for 要写成htmlFor,因为for已经成了关键字。 10、componentWillUpdate中可以直接改变state的值,而不能用setState。 11、如果使用es6class类继承react的component组件,constructor中必须调用super,因为子类需要用super继承component的this,否则实例化的时候会报错。 本篇文章到这就结束了(想看更多就到PHP中文网React使用手册栏目中学习),有问题的可以在下方留言提问。react-router
const chooseProducts = (location, cb) => {
require.ensure([], require => {
cb(null, require('../Component/chooseProducts').default)
},'chooseProducts')
}
const helpCenter = (location, cb) => {
require.ensure([], require => {
cb(null, require('../Component/helpCenter').default)
},'helpCenter')
}
const saleRecord = (location, cb) => {
require.ensure([], require => {
cb(null, require('../Component/saleRecord').default)
},'saleRecord')
}
const RouteConfig = (
<router>
<route>
<indexroute></indexroute>//首页
<route></route>
<route></route>//帮助中心
<route></route>//销售记录
<redirect></redirect>
</route>
</router>
);
コンポーネント間の通信
まず redux について話しましょう:
redux は主に、store、reducer、action の 3 つの部分で構成されます。
let unsubscribe = store.subscribe(() => {console.log('state发生了变化')})const reducer = combineReducers({
a: doSomethingWithA,
b: processB,
c: c
})
react-redux
function mapStateToProps(state) {
return { todos: state.todos };
}
function mapDispatchToProps(dispatch) {
return {
todoActions: bindActionCreators(todoActionCreators, dispatch),
counterActions: bindActionCreators(counterActionCreators, dispatch)
};
}
以下は完全な React --> redux --> React プロセスです:
プロジェクト構築
import { Router, Route, Redirect, IndexRoute, browserHistory, hashHistory } from 'react-router';
3. 要件に従ってトップレベル ui コンポーネントを作成し、各トップレベル ui コンポーネントを作成します。ページに相当します。
componentWillMount とcomponentDidMount は初期化中にのみ呼び出されます。
3. Reducer はコンポーネントの更新を開始するために新しいオブジェクトを返す必要があります
connect 関数では、新しい状態と古い状態が軽く比較されるため、状態の値が変化するだけで参照アドレスが変化しない場合、connect は考慮します。それらは同じであり、更新をトリガーするものではありません。 require.ensure([], require => {
cb(null, require('../Component/saleRecord').default)
},'saleRecord')
以上がReact の全体的なプロセスは何ですか? React の全体的なプロセスの紹介 (例付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。