検索
ホームページウェブフロントエンドjsチュートリアルReactの制御コンポーネントと非制御コンポーネントの詳細な説明

この記事では主に React の制御コンポーネントと非制御コンポーネントについて詳しく説明します。公式 Web サイトや国内 Web サイトには制御コンポーネントと非制御コンポーネントに関する情報があまりありません。気にしないでください。これは、さまざまな規模のプロジェクトのニーズを満たす React の力を示しています。たとえば、ListView のような単純なデータ表示を実行してデータをキャプチャするだけであれば、for ループと {} で十分ですが、バックグラウンド システムには多数のレポートが存在します。さまざまなフォームがリンクされているため、コンポーネントはまったく機能しません。 {}就足够了,但后台系统存在大量报表,不同的表单联动,缺了受控组件真的不行。

受控组件与非受控组件是React处理表单的入口。从React的思路来讲,作者肯定让数据控制一切,或者简单的理解为,页面的生成与更新得忠实地执行JSX的指令。

但是表单元素有其特殊之处,用户可以通过键盘输入与鼠标选择,改变界面的显示。界面的改变也意味着有一些数据被改动,比较明显的是input的value,textarea的innerHTML,radio/checkbox的checked,不太明显的是option的selectedselectedIndex,这两个是被动修改的。

<input>

当input.value是由组件的state.value拍出来的,当用户进行输入修改后,然后JSX再次重刷视图,这时input.value是采取用户的新值还是state的新值?基于这个分歧,React给出一个折衷的方案,两者都支持,于是就产生了今天的主题了。

React认为value/checked不能单独存在,需要与onInput/onChange/disabed/readOnly等控制value/checked的属性或事件一起使用。 它们共同构成受控组件,受控是受JSX的控制。如果用户没有写这些额外的属性与事件,那么框架内部会给它添加一些事件,如onClick, onInput, onChange,阻止你进行输入或选择,让你无法修改它的值。在框架内部,有一个顽固的变量,我称之为 persistValue,它一直保持JSX上次赋给它的值,只能让内部事件修改它。

因此我们可以断言,受控组件是可通过事件完成的对value的控制。

在受控组件中,persistValue总能被刷新。

我们再看非受控组件,既然value/checked已经被占用了,React启用了HTML中另一组被忽略的属性defaultValue/defaultChecked。一般认为它们是与value/checked相通的,即,value不存在的情况下,defaultValue的值就当作是value。

上面我们已经说过,表单元素的显示情况是由内部的 persistValue 控制的,因此defaultXXX也会同步persistValue,然后再由persistValue同步DOM。但非受控组件的出发点是忠实于用户操作,如果用户在代码中

input.value = "xxxx"

以后

<input>

就再不生效,一直是xxxx。

它怎么做到这一点,怎么辨识这个修改是来自框架内部或外部呢?我翻看了一下React的源码,原来它有一个叫valueTracker的东西跟踪用户的输入

var tracker = {
    getValue: function () {
      return currentValue;
    },
    setValue: function (value) {
      currentValue = '' + value;
    },
    stopTracking: function () {
      detachTracker(node);
      delete node[valueField];
    }
  };
  return tracker;
}

这个东西又是通过Object.defineProperty打进元素的value/checked的内部,因此就知晓用户对它的取值赋值操作。

但value/checked还是两个很核心的属性,涉及到太多内部机制(比如说value与oninput, onchange, 输入法事件oncompositionstart,
compositionchange, oncompositionend, onpaste, oncut),为了平缓地修改value/checked,
还要用到Object.getOwnPropertyDescriptor。如果我要兼容IE8,没有这么高级的玩艺儿。我采取另一种更安全的方式,
只用Object.defineProperty修改defaultValue/defaultChecked

首先我为元素添加一个_uncontrolled的属性,用来表示我已经劫持过defaultXXX。 然后描述对象 (Object.defineProperty的第三个参数)的set方法里面再添加一个开关,_observing。在框架内部更新视图,此值为false,更新完,它置为true。

这样就知晓 input.defaultValue = "xxx"时,这是由用户还是框架修改的。

f (!dom._uncontrolled) {
    dom._uncontrolled = true;
    inputMonitor.observe(dom, name); //重写defaultXXX的setter/getter
}
dom._observing = false;//此时是框架在修改视图,因此需要关闭开关
dom[name] = val;
dom._observing = true;//打开开关,来监听用户的修改行为

inputMonitor的实现如下

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) {}
};

又不小心贴了这么烧脑的代码,这是码农的坏毛病。不过,到这步,大家都明白,无论是官方react还是anu/qreact都是通过Object.defineProperty来控制用户的输入的。

于是我们可以理解以下的代码的行为了

    var a =  ReactDOM.render(<textarea></textarea>, container);
    ReactDOM.render(<textarea></textarea>, container);
    ReactDOM.render(<textarea></textarea>, container);
    expect(a.defaultValue).toBe("noise");
    expect(a.value).toBe("foo");
    expect(a.textContent).toBe("noise");
    expect(a.innerHTML).toBe("noise");

由于用户一直没有手动修改 defaultValue,dom._setValue 一直为false/undefined,因此 _persistValue

制御されたコンポーネントと制御されていないコンポーネントは、React がフォームを処理するためのエントリ ポイントです。 React の観点から見ると、作成者はデータにすべてを制御させるか、ページの生成と更新で JSX 命令を忠実に実行する必要があることを単に理解する必要があります。

しかし、フォーム要素には独自の特別な機能があり、ユーザーはキーボード入力やマウスの選択を通じてインターフェイスの表示を変更できます。インターフェイスの変更は、一部のデータが変更されたことも意味します。より明らかなのは、input の、textarea のinnerHTML、radio/checkbox のチェック済みです。 > 、あまり明白ではありませんが、 オプションのselectedselectedIndex は受動的に変更されます。

var renderTextarea = function(component, container) {
    if (!container) {
        container = document.createElement("p");
    }
    const node = ReactDOM.render(component, container);
    node.defaultValue = node.innerHTML.replace(/^\n/, "");
    return node;
};

const container = document.createElement("p");
//注意这个方法,用户在renderTextarea中手动改变了defaultValue,_setValue就变成true
const node = renderTextarea(<textarea></textarea>, container);

expect(node.value).toBe("giraffe");

// _setValue后,gorilla就不能同步到_persistValue,因此还是giraffe
renderTextarea(<textarea></textarea>, container);
//  expect(node.value).toEqual("giraffe");

node.value = "cat";
// 这个又是什么回事了呢,因此非监控属性是在diffProps中批量处理的,在监控属性,则是在更后的方法中处理
// 检测到node.value !== _persistValue,于是重写 _persistValue = node.value,于是输出cat
renderTextarea(<textarea></textarea>, container);
expect(node.value).toEqual("cat");
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を同期します。ただし、制御されていないコンポーネントの出発点は、ユーザーの操作に忠実であることです。コード内でユーザー 🎜
//精确匹配
var dom = ReactDOM.render(
    <select>
        <option>aaa</option>
        <option>xxx</option>
        <option>bbb</option>
        <option>ccc</option>
    </select>,
    container
);
expect(dom.options[2].selected).toBe(true);//选中第三个
🎜 が指定されている場合、その機能は無効になり、常に xxxx になります。 🎜🎜これはどのように行われるのでしょうか?また、この変更がフレームワークの内側から来たのか外側から来たのかをどのように識別するのでしょうか? Reactのソースコードを調べてみたところ、ユーザー入力を追跡するためのvalueTrackerというものが存在することが分かりました🎜
//模糊匹配
var dom = ReactDOM.render(
    <select>
        <option>aaa</option>
        <option>xxx</option>
        <option>ccc</option>
    </select>,
    container
);
expect(dom.options[2].selected).toBe(true);//选中第二个
🎜これはObject.definePropertyを通じて要素の値に入力/チェックされるため、ユーザーのアクセスがわかります値の割り当て操作。 🎜🎜しかし、value/checked は依然として非常に多くの内部メカニズム (value と oninput、onchange、入力メソッド イベント oncompositionstart、
compositionchange、oncompositionend、onpaste、oncut など) を含む 2 つの非常に中心的な属性であり、To をスムーズに行うためには必要です。値/チェックを変更する場合、
Object.getOwnPropertyDescriptor も使用します。 IE8に対応したいなら、これほど高機能なガジェットはありません。私は別のより安全なアプローチを採用し、
Object.defineProperty を使用して defaultValue/defaultChecked を変更します。 🎜🎜まず、要素に _uncontrolled 属性を追加して、defaultXXX をハイジャックしたことを示します。 次に、別のスイッチ _observing を記述オブジェクトの set メソッド (Object.defineProperty の 3 番目のパラメーター) に追加します。ビューがフレーム内で更新されると、この値は false になり、更新後は true に設定されます。 🎜🎜これにより、input.defaultValue = "xxx" がユーザーによって変更されたのかフレームワークによって変更されたのかがわかります。 🎜rrreee🎜inputMonitor の実装は以下の通りです🎜rrreee🎜プログラマーの悪い癖で、うっかりこのような頭を使うコードを投稿してしまいました。ただし、この時点では、公式の React と anu/qreact の両方が Object.defineProperty を通じてユーザー入力を制御していることを誰もが理解しています。 🎜🎜したがって、次のコードの動作を理解できます🎜rrreee🎜ユーザーが手動でdefaultValueを変更していないため、dom._setValue は常にfalse/未定義です。 _persistValue はいつでも変更できます。 🎜🎜別の例: 🎜rrreee🎜 もちろん、フォーム要素には多くの種類があり、各フォーム要素にはデフォルトの動作もあります。 🎜

纯文本类:text, textarea, JSX的值,总是往字符串转换
type="number"的控制,值总是为数字,不填或为“”则转换为“0”
radio有联动效果,同一父节点下的相同name的radio控制只能选择一个。
select的value/defaultValue支持数组,不做转换,但用户对底下的option元素做增删操作,selected会跟着变动。

此外select还有模糊匹配与精确匹配之分。

//精确匹配
var dom = ReactDOM.render(
    <select>
        <option>aaa</option>
        <option>xxx</option>
        <option>bbb</option>
        <option>ccc</option>
    </select>,
    container
);
expect(dom.options[2].selected).toBe(true);//选中第三个
//模糊匹配
var dom = ReactDOM.render(
    <select>
        <option>aaa</option>
        <option>xxx</option>
        <option>ccc</option>
    </select>,
    container
);
expect(dom.options[2].selected).toBe(true);//选中第二个

凡此种种,React/anu都是做了大量工作,迷你如preact/react-lite之流则可能遇坑。

相关推荐:

react如何实现菜单权限控制?

React 内部机制探秘

React中组件的写法有哪些


以上がReactの制御コンポーネントと非制御コンポーネントの詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
C/CからJavaScriptへ:すべてがどのように機能するかC/CからJavaScriptへ:すべてがどのように機能するかApr 14, 2025 am 12:05 AM

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

JavaScriptエンジン:実装の比較JavaScriptエンジン:実装の比較Apr 13, 2025 am 12:05 AM

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

ブラウザを超えて:現実世界のJavaScriptブラウザを超えて:現実世界のJavaScriptApr 12, 2025 am 12:06 AM

現実世界におけるJavaScriptのアプリケーションには、サーバー側のプログラミング、モバイルアプリケーション開発、モノのインターネット制御が含まれます。 2。モバイルアプリケーションの開発は、ReactNativeを通じて実行され、クロスプラットフォームの展開をサポートします。 3.ハードウェアの相互作用に適したJohnny-Fiveライブラリを介したIoTデバイス制御に使用されます。

next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)Apr 11, 2025 am 08:23 AM

私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます

next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合)Apr 11, 2025 am 08:22 AM

この記事では、許可によって保護されたバックエンドとのフロントエンド統合を示し、next.jsを使用して機能的なedtech SaaSアプリケーションを構築します。 FrontEndはユーザーのアクセス許可を取得してUIの可視性を制御し、APIリクエストがロールベースに付着することを保証します

JavaScript:Web言語の汎用性の調査JavaScript:Web言語の汎用性の調査Apr 11, 2025 am 12:01 AM

JavaScriptは、現代のWeb開発のコア言語であり、その多様性と柔軟性に広く使用されています。 1)フロントエンド開発:DOM操作と最新のフレームワーク(React、Vue.JS、Angularなど)を通じて、動的なWebページとシングルページアプリケーションを構築します。 2)サーバー側の開発:node.jsは、非ブロッキングI/Oモデルを使用して、高い並行性とリアルタイムアプリケーションを処理します。 3)モバイルおよびデスクトップアプリケーション開発:クロスプラットフォーム開発は、反応および電子を通じて実現され、開発効率を向上させます。

JavaScriptの進化:現在の傾向と将来の見通しJavaScriptの進化:現在の傾向と将来の見通しApr 10, 2025 am 09:33 AM

JavaScriptの最新トレンドには、TypeScriptの台頭、最新のフレームワークとライブラリの人気、WebAssemblyの適用が含まれます。将来の見通しは、より強力なタイプシステム、サーバー側のJavaScriptの開発、人工知能と機械学習の拡大、およびIoTおよびEDGEコンピューティングの可能性をカバーしています。

javascriptの分解:それが何をするのか、なぜそれが重要なのかjavascriptの分解:それが何をするのか、なぜそれが重要なのかApr 09, 2025 am 12:07 AM

JavaScriptは現代のWeb開発の基礎であり、その主な機能には、イベント駆動型のプログラミング、動的コンテンツ生成、非同期プログラミングが含まれます。 1)イベント駆動型プログラミングにより、Webページはユーザー操作に応じて動的に変更できます。 2)動的コンテンツ生成により、条件に応じてページコンテンツを調整できます。 3)非同期プログラミングにより、ユーザーインターフェイスがブロックされないようにします。 JavaScriptは、Webインタラクション、シングルページアプリケーション、サーバー側の開発で広く使用されており、ユーザーエクスペリエンスとクロスプラットフォーム開発の柔軟性を大幅に改善しています。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

MantisBT

MantisBT

Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

DVWA

DVWA

Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

SecLists

SecLists

SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。