この記事では、React の詳細なプログラミングの制御コンポーネントと非制御コンポーネントを主に紹介し、参考として提供します。
公式 Web サイトや国内 Web サイトには、規制コンポーネントと非規制コンポーネントに関する情報があまりありません。これはオプションであると考えており、気にしない人もいます。これは、さまざまな規模のプロジェクトのニーズを満たす React の力を示しています。たとえば、ListView のような単純なデータ表示を行ってデータをキャプチャするだけであれば、for ループと {} で十分ですが、バックグラウンド システムには多数のレポートが存在し、さまざまなフォームが連携されます。制御されたコンポーネントでは実際には機能しません。
制御されたコンポーネントと制御されていないコンポーネントは、React がフォームを処理するためのエントリ ポイントです。 React の観点から見ると、作成者はデータにすべてを制御させるか、ページの生成と更新で JSX 命令を忠実に実行する必要があることを単に理解する必要があります。
しかし、フォーム要素には独自の特別な機能があり、ユーザーはキーボード入力やマウスの選択を通じてインターフェイスの表示を変更できます。インターフェースの変更は、一部のデータが変更されたことも意味します。より明らかなものは、入力の値、テキストエリアの innerHTML、およびラジオ/チェックボックスのチェック済みのものです。このオプションは受動的に変更されます。
<input value="{this.state.value}"/>
input.value がコンポーネントの state.value から取得されるとき、ユーザーが入力を変更し、JSX がビューを再描画するとき、input.value はユーザーの新しい値を取得しますか、それとも状態の新しい値を取得しますか?この意見の相違に基づいて、React は両方から支持される妥協的な解決策を提示し、今日のトピックが生まれました。
React は、value/checked が単独で存在することはできず、onInput/onChange/disabed/readOnly および value/checked を制御する他のプロパティまたはイベントと一緒に使用する必要があると考えています。 これらは一緒になって、JSX によって制御される制御コンポーネントを形成します。ユーザーがこれらの追加のプロパティとイベントを作成しない場合、フレームワークは onClick、onInput、onChange などのいくつかのイベントを内部で追加するため、入力や選択ができなくなり、その値を変更できなくなります。フレームワーク内には、persistValue と呼ぶ頑固な変数があります。この変数は、JSX によって最後に割り当てられた値を保持し、内部イベントによってのみ変更できます。
したがって、制御されるコンポーネントは、イベントを通じて完了できる価値の制御であると断言できます。
制御されたコンポーネントでは、persistValue はいつでも更新できます。
制御されていないコンポーネントをもう一度見てみましょう。 value/checked はすでに占有されているため、React は HTML で別の無視される属性セット、defaultValue/defaultChecked を有効にします。一般に、これらは value/checked と同様であると考えられています。つまり、value が存在しない場合、defaultValue の値が value とみなされます。
フォーム要素の表示は内部のpersistValueによって制御されると上で述べました。そのため、defaultXXXもpersistValueを同期し、次にpersistValueがDOMを同期します。ただし、制御されていないコンポーネントの出発点は、ユーザーの操作に忠実であることです。コード内でユーザー
input.value = "xxxx"
が指定されている場合、その機能は無効になり、常に xxxx になります。
これはどのように行われるのでしょうか?また、この変更がフレームワークの内側から来たのか外側から来たのかをどのように識別するのでしょうか? Reactのソースコードを調べてみたところ、ユーザー入力を追跡するためのvalueTrackerというものが存在することが分かりました
<input defaultvalue="{this.state.value}"/>
これはObject.definePropertyを通じて要素の値に入力/チェックされるため、ユーザーのアクセスがわかります値の割り当て操作。
しかし、value/checked は依然として 2 つの非常にコアな属性であり、値をスムーズに変更するために、あまりにも多くの内部メカニズム (value と oninput、onchange、入力メソッド イベント oncompositionstart、
compositionchange、oncompositionend、onpaste、oncut など) を必要とします /チェックを入れると、
Object.getOwnPropertyDescriptor も使用する必要があります。 IE8に対応したいなら、これほど高機能なガジェットはありません。私は別の安全な方法を採用しています。
Object.defineProperty を使用して、defaultValue/defaultChecked を変更するだけです。
まず、要素に _uncontrolled 属性を追加して、defaultXXX をハイジャックしたことを示します。 次に、オブジェクトを記述する set メソッド (Object.defineProperty の 3 番目のパラメーター) に別のスイッチ _observing を追加します。ビューがフレーム内で更新されると、この値は false になり、更新後は true に設定されます。
これにより、input.defaultValue = "xxx" がユーザーによって変更されたのかフレームワークによって変更されたのかがわかります。
var tracker = { getValue: function () { return currentValue; }, setValue: function (value) { currentValue = '' + value; }, stopTracking: function () { detachTracker(node); delete node[valueField]; } }; return tracker; }
inputMonitor の実装は以下の通りです
if (!dom._uncontrolled) { dom._uncontrolled = true; inputMonitor.observe(dom, name); //重写defaultXXX的setter/getter } dom._observing = false;//此时是框架在修改视图,因此需要关闭开关 dom[name] = val; dom._observing = true;//打开开关,来监听用户的修改行为
プログラマーの悪い癖で、うっかりこのような頭を使うコードを投稿してしまいました。ただし、この時点では、公式の React と anu/qreact の両方が Object.defineProperty を通じてユーザー入力を制御していることを誰もが理解しています。
したがって、次のコードの動作を理解することができます
export var inputMonitor = {}; var rcheck = /checked|radio/; var describe = { set: function(value) { var controllProp = rcheck.test(this.type) ? "checked" : "value"; if (this.type === "textarea") { this.innerHTML = value; } if (!this._observing) { if (!this._setValue) { //defaultXXX只会同步一次_persistValue var parsedValue = (this[controllProp] = value); this._persistValue = Array.isArray(value) ? value : parsedValue; this._setValue = true; } } else { //如果用户私下改变defaultValue,那么_setValue会被抺掉 this._setValue = value == null ? false : true; } this._defaultValue = value; }, get: function() { return this._defaultValue; }, configurable: true }; inputMonitor.observe = function(dom, name) { try { if ("_persistValue" in dom) { dom._setValue = true; } Object.defineProperty(dom, name, describe); } catch (e) {} };
ユーザーがdefaultValueを手動で変更していないため、dom._setValueは常にfalse/未定義であるため、_persistValueはいつでも変更できます。
別の例:
var a = ReactDOM.render(<textarea defaultValue="foo" />, container); ReactDOM.render(<textarea defaultValue="bar" />, container); ReactDOM.render(<textarea defaultValue="noise" />, container); expect(a.defaultValue).toBe("noise"); expect(a.value).toBe("foo"); expect(a.textContent).toBe("noise"); expect(a.innerHTML).toBe("noise");
プレーンテキストクラス: text、textarea、JSX 値は常に文字列に変換されます
type="number" コントロール、値が入力されていない場合、または " の場合、値は常に数値になります。 「「0」に変換
ラジオには連動効果があります。同じ親ノードにある同じ名前のラジオコントロールは1つだけ選択できます。
Select の value/defaultValue は配列をサポートしており、変換は実行されません。ただし、ユーザーがその下にある option 要素を追加または削除すると、selected はそれに応じて変更されます。
さらに、選択はあいまい一致と完全一致に分けることができます。
//精确匹配 var dom = ReactDOM.render( <select value={222}> <option value={111}>aaa</option> <option value={"222"}>xxx</option> <option value={222}>bbb</option> <option value={333}>ccc</option> </select>, container ); expect(dom.options[2].selected).toBe(true);//选中第三个
//模糊匹配 var dom = ReactDOM.render( <select value={222}> <option value={111}>aaa</option> <option value={"222"}>xxx</option> <option value={333}>ccc</option> </select>, container ); expect(dom.options[2].selected).toBe(true);//选中第二个
凡此种种,React/anu都是做了大量工作,迷你如preact/react-lite之流则可能遇坑。
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
以上がReact の制御コンポーネントと非制御コンポーネントの詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。