Vue3 の 2 つの主要なレスポンシブ ツールである ref と reactive の詳細な説明
Vue2のdefinePropertyによるデータ応答性と比較して、Vue3ではデータ応答処理の分業化が明確になっており、refとreactiveの2つの関数でデータをパッケージ化し、統合されたAPIで開発者に公開することでデータ応答を実現しています。では、それらの違いは何でしょうか?例文と一緒に学んでいきましょう!
ref: 基本データ型と参照データ型の応答型
を定義します。つまり、ref(value)、この値の型は基本データ型または参照データ型にすることができますが、js で使用する場合は、property.value
の形式で使用する必要があり、テンプレート データ内で直接呼び出すことができます。
<template> <div> <div><button @click="changeValue">修改</button></div> <div> <p>当前strRef:{{ strRef }}</p> <p>当前objRef:姓名:{{ objRef.name }} 爱好:{{ objRef.hobboy }}</p> <p>当前arrRef:{{ arrRef }}</p> </div> </div> </template> <script> import { defineComponent, ref, shallowRef } from 'vue' export default defineComponent({ setup () { const strRef = ref('sapper');// 基本数据类型 const arrRef = ref([1, 3, 2]);// 数组类型 const objRef = ref({ // 对象类型 name: 'sapper', hobboy: ['吉他', '原神'] }) const changeValue = () => { strRef.value = '工兵'; arrRef.value[1] = 4; objRef.value.hobboy[1] = '滑冰'; } return {strRef,objRef,arrRef,changeValue} } }) </script>
reactive:基本的なデータ型をサポートしていない参照型データのリアクティブ型を定義します
。基本的なデータ型を記述する必要がある場合は、次のことしかできません。それらをオブジェクトに入れる、つまり reactive(value)、この値の型は参照型である必要があります。 [関連する推奨事項: vuejs ビデオ チュートリアル 、Web フロントエンド開発 ]
<template> <div> <div><button @click="changeValue">修改</button></div> <div> <div>当前objReactive: <br/> 姓名:{{ objReactive.name }}<br/> 爱好:{{ objReactive.hobboy }} </div> <div>当前arrReactive:{{ arrReactive }}</div> </div> </div> </template> <script> import { defineComponent, reactive } from 'vue' export default defineComponent({ setup () { const arrReactive = reactive([1, 3, 2]);// 数组类型 const objReactive = reactive({ // 对象类型 name: 'sapper', hobboy: ['吉他', '原神'] }) const changeValue = () => { arrReactive[1] = 4; objReactive.name = '工兵'; objReactive.hobboy[1] = '滑冰'; } return {objReactive,arrReactive,changeValue} } }) </script>
上記 2 つの例から、データの種類に関係なく、ref ref で定義されたデータを呼び出すには .value
である必要があります。参照データ型の場合、コードが美しくないことがわかります。そのため、一般的に を定義するには reactive を使用することをお勧めします。参照型データの場合; 基本データ型の場合、ref または reactive を使用して を定義できます。ここで ref と reactive の使用の違いを理解したところで、引き続きそれらの応答原理の違いを調べてみましょう。
ref を明らかにする
上記の例から、まず基本データ型 (strRef) と参照データ型 (arrRef) の ref 内部カプセル化構造を出力して調べます。 、ObjRef)どのように見えますか?次の 3 つの図に示すように#上の図からわかるように、データの種類に関係なく、は、ref カプセル化されたデータの場合 これらはすべて RefImpl オブジェクト (参照実装を意味する referenceimplement
の省略形です。各 RefImpl オブジェクトには 6 つの属性があります:
dep: これは Set タイプのデータで、現在の ref 値によって収集された依存関係を保存するために使用されます。
__ v _ isRef: ビットをマークします。ビットが ref で定義されている限り、現在のデータを Ref、つまりその値としてマークします。は true としてマークされます。
__ v _ isShallow:shallowRef で定義されたデータであるかどうかを判断します。
ref とは異なり、shallowRef を使用して参照型の応答性を作成すると、深い属性が変更され、応答性がなくなります。 .value への参照に対してのみ発生します。
const state = shallowRef({ count: 1 }) // 不会触发更改 state.value.count = 2 // 会触发更改 state.value = { count: 2 }
ログイン後にコピー_ rawValue: 渡されたパラメータが # の場合、現在の ref 値に対応する元の値 を保存するために使用されます。 ## オブジェクト
__ value。これは、変換前に元の値
を保存するために使用されます。それ以外の場合、_ value は _ rawValue と同じです。 : 渡されたパラメータが - object
の場合、ref の現在の値を 保存するために使用されます。
とリアクティブ関数
によって変換された値を保存するために使用されます。それ以外の場合、_ value は _ rawValue と同じです。上記の例から、参照型データの場合、その値はプロキシ オブジェクトであり、実際にはデータをカプセル化した後のリアクティブ オブジェクトであることがわかります (後述)。まず、下の図を見て、_ rawValue がレスポンシブ処理を行わない元の値であることを確認し、次に、リアクティブな応答で処理されたプロキシ オブジェクトである _ value を見てみましょう。_ rawValue
_ value
は、参照型データを応答的に処理する必要があるかどうかを区別するためのものです。
#value
ref がデータに対してどのような属性をカプセル化するのかがわかったので、ソース コードが上記の 6 つの属性に値を割り当てる方法を調べてみましょう。
ref 関数
: Vue3 は ref 関数を開発者に公開しており、実際には createRef 関数をカプセル化しています。createRef function
: パラメータは 2 つあり、1 つは応答 のために処理されるデータ - で、もう 1 つは
です。データがshallowRefに対して定義されたData であるかどうかを判断します。主に行うことは、現在の rawValue (応答用にまだ処理されていないデータ) が ref 型データであるかどうかを判断し、RefImpl インスタンス オブジェクトを作成することです。
function createRef(rawValue: unknown, shallow: boolean) { if (isRef(rawValue)) { return rawValue } return new RefImpl(rawValue, shallow) }
ログイン後にコピー RefImpl类:创建RefImpl类给_ rawValue和_ value属性赋值,判断当前定义的ref数据是否为shallowRef定义的数据,然后获取响应性值时对数据依赖进行收集并返回_ value,修改响应式值时修改并通知依赖更新。
ref定义的数据为什么需要带.value调用数据? 就是
因为RefImpl类暴露给实例对象的get、set方法是value
,所以在调用的时候,需要带上。
export function ref(value?: unknown) { return createRef(value, false) }
其实,RefImpl实例关键就在于trackRefValue(this)
和triggerRefValue(this, newVal)
的两个函数的处理,我们大概也知道它们就是依赖收集、依赖更新。这里就不一一探讨。
揭秘Reactive
上面也说了reactive封装数据的用法,它只支持传入引用类型数据(数组、对象),如果需要在reactive中使用基础类型只能放在对象中。既然这样我们来探讨一下reactive函数究竟做了什么?
const arrReactive = reactive([1, 3, 2]);// 数组类型 const objReactive = reactive({ // 对象类型 name: 'sapper', hobboy: ['吉他', '原神'] }) const changeValue = () => { arrReactive[1] = 4; objReactive.name = '工兵'; objReactive.hobboy[1] = '滑冰'; console.log('arrReactive',arrReactive); console.log('objReactive',objReactive); }
从上图可以看出,使用reactive封装的数据返回的都是一个proxy对象,proxy就是代理,如把一个对象代理到另一个对象,好比如房子所有者,代理房子给二手房东销售,二手房东就可以拥有房子销售权利。从上图我们可以看到Proxy对象有三个属性:
[[Handler]]: 创建Proxy对象传入的第二个参数,是对当前需要代理的目标target进行一些相关配置处理。
[[Target]]:需要代理的目标target,也就是被代理的目标。
[[IsRevoked]]:表示是否可撤销,生成可撤销的proxy对象用Proxy.revocable()方法。 那么Proxy对象可以做什么?我们看看下面例子:
const houseOwner = {home:'房源',price:1200,type:'一房一厅'}; const proxyOwner = new Proxy(houseOwner,{ get:function (target,key){ console.log(`${key}属性被访问!`) return target[key]; }, set:function(target,key,value){ if(target[key]===value){ return; } target[key] = value; return target[key]; }, }) console.log(proxyOwner); proxyOwner.price = 1300;// 对被代理对象的修改 proxyOwner.remark = '采光点好!'; console.log(proxyOwner.price);// price属性被访问
ログイン後にコピー
从这个例子,可以看出Proxy对象的第二个参数给代理目标带上相关属性:set方法、get方法,再回到reactive封装的数据中,数据的Handler属性给数据带上了五个属性:deleteProperty
、get
、set
、has
、ownKeys
。这五个属性怎么来的?我们一起探讨一下Vue3的源码实现:
// 源码位置:core-main/packages/reactivity/src/reactive.ts // Vue3中暴露给开发者的是reactive方法 export function reactive(target: object) { // 判断target是否只读,是就不做处理 if (isReadonly(target)) { return target } return createReactiveObject( target, false, mutableHandlers, mutableCollectionHandlers, reactiveMap ) }
createReactiveObject函数主要为了创建Proxy实例对象,参数传了五个属性: target
(目标数据)、isReadonly
(target是否只读)、mutableHandlers
(ProxyHandler)、mutableCollectionHandlers
(ProxyHandler类型)、proxyMap
(数据集合)。我们先了解一波createReactiveObject函数:
ReactiveFlags:响应式数据标记。
export const enum ReactiveFlags { SKIP = '__v_skip',// 标记对象不可进行代理 IS_REACTIVE = '__v_isReactive',// 是否是Reactive封装的 IS_READONLY = '__v_isReadonly',// 是否只读 IS_SHALLOW = '__v_isShallow',// 是否是shallowRef封装的 RAW = '__v_raw'// 是否是proxy原始的target }
ログイン後にコピーTargetType:target的数据类型。
const enum TargetType { INVALID = 0, COMMON = 1,// Array、Object类型 COLLECTION = 2 // Set、Map、WaekMap、WeakSet类型 }
ログイン後にコピーbaseHandlers:对于Array、Object类型数据,Proxy实例的第二个参数。传入的baseHandlers就是
mutableHandlers
。这个函数主要是为了给Proxy对象带上五个属性。// 源码位置:core-main/packages/reactivity/src/baseHandlers.ts export const mutableHandlers: ProxyHandler<object> = { // createGetter() 主要实现依赖收集和Reflect.set(target, key, value, receiver) get, // createSetter() 主要实现通知依赖更新和Reflect.get(target, key, receiver) set, // deleteProperty() 主要是删除target的指定key的属性Reflect.deleteProperty(target, key) deleteProperty, // has() 主要是判断target是否存在指定key的属性,Reflect.has(target, key) has, // ownKeys() 主要是获取target的key数组,Reflect.ownKeys(target) ownKeys }
ログイン後にコピーcollectionHandlers:对于Set、Map、WaekMap、WeakSet类型数据,Proxy实例的第二个参数。传入的baseHandlers就是
mutableCollectionHandlers
。mutableCollectionHandlers主要是对 set、map、weakSet、weakMap 四种类型的对象进行劫持。// 源码位置:core-main/packages/reactivity/src/mutableCollectionHandlers.ts export const mutableCollectionHandlers: ProxyHandler<CollectionTypes> = { get: /*#__PURE__*/ createInstrumentationGetter(false, false) } function createInstrumentationGetter(isReadonly: boolean, shallow: boolean) { const instrumentations = shallow? isReadonly? shallowReadonlyInstrumentations: shallowInstrumentations : isReadonly? readonlyInstrumentations: mutableInstrumentations return (target: CollectionTypes,key: string | symbol,receiver: CollectionTypes) => { ... return Reflect.get( hasOwn(instrumentations, key) && key in target? instrumentations:target, key, receiver ) } }
ログイン後にコピー总结:
-
ref:定义基本数据类型、引用数据类型的响应式。封装数据类型为ref类型,主要就是
创建了RefImpl实例对象
。 -
reactive:定义引用类型数据的响应式,不支持基本数据类型,如果需要写基本数据类型只能是放在对象中。封装数据为reactive类型,主要是
创建了Proxy实例对象
,通过Reflect实现数据的获取与修改。
以上がVue3 の 2 つの主要なレスポンシブ ツールである ref と reactive の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。
-
ref:定义基本数据类型、引用数据类型的响应式。封装数据类型为ref类型,主要就是

ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

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

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









モバイル デバイスの普及に伴い、Web デザインでは、優れたユーザー エクスペリエンスを実現するために、デバイスの解像度やさまざまな端末の画面サイズなどの要素を考慮する必要があります。 Web サイトのレスポンシブ デザインを実装する場合、画像カルーセル効果を使用して限られた視覚ウィンドウに複数の画像のコンテンツを表示することが必要になることがよくありますが、同時に Web サイトの視覚効果も高めることができます。この記事では、CSS を使用してレスポンシブ画像の自動カルーセル効果を実現する方法を紹介し、コード例と分析を示します。実装のアイデア レスポンシブ画像カルーセルの実装は、CSS フレックス レイアウトを通じて実装できます。存在する

HTML、CSS、jQuery を使用してレスポンシブ タグ クラウドを作成する方法 タグ クラウドは、さまざまなキーワードやタグを表示するために使用される一般的な Web 要素です。通常、キーワードの重要性がさまざまなフォント サイズまたは色で表示されます。この記事では、HTML、CSS、jQueryを使ってレスポンシブタグクラウドを作成する方法と、具体的なコード例を紹介します。 HTML 構造の作成 まず、HTML でタグ クラウドの基本構造を作成する必要があります。順序なしリストを使用してタグを表すことができます

CSS を使用してレスポンシブなスライド メニューを実装するチュートリアルには、特定のコード サンプルが必要です。現代の Web デザインでは、レスポンシブ デザインは必須のスキルとなっています。さまざまなデバイスや画面サイズに対応するには、Web サイトに応答性の高いメニューを追加する必要があります。今日は、CSS を使用して応答性の高いスライド メニューを実装し、具体的なコード例を示します。まず、実装を見てみましょう。画面幅が一定のしきい値より小さい場合は自動的に折りたたまれ、メニューボタンをクリックすると展開するナビゲーションバーを作成します。

HTML、CSS、jQuery を使用して応答性の高いスクロール通知バーを作成する方法 モバイル デバイスの普及と、Web サイトへのアクセス エクスペリエンスに対するユーザーの要件の増加に伴い、応答性の高いスクロール通知バーの設計がますます重要になっています。レスポンシブ デザインにより、Web サイトがさまざまなデバイスで適切に表示され、ユーザーが通知コンテンツを簡単に表示できるようになります。この記事では、HTML、CSS、jQuery を使用して応答性の高いスクロール通知バーを作成する方法を紹介し、具体的なコード例を示します。まず、HTM を作成する必要があります

HTML と CSS を使用してレスポンシブなカルーセル レイアウトを作成する方法 カルーセルは、最新の Web デザインの一般的な要素です。ユーザーの注意を引いたり、複数のコンテンツや画像を表示したり、自動的に切り替えたりすることができます。この記事では、HTMLとCSSを使ってレスポンシブカルーセルレイアウトを作成する方法を紹介します。まず、基本的な HTML 構造を作成し、必要な CSS スタイルを追加する必要があります。以下は単純な HTML 構造です: <!DOCTYPEhtml&g

Webman を使用したレスポンシブ Web サイト開発のヒント 今日のデジタル時代では、人々はインターネットにアクセスするためにモバイル デバイスにますます依存しています。より良いユーザー エクスペリエンスを提供し、さまざまな画面サイズに適応するために、レスポンシブな Web サイト開発が重要なトレンドになっています。 Webman は強力なフレームワークとして、レスポンシブな Web サイトの開発を実現するための多くのツールとテクノロジーを提供します。この記事では、メディア クエリの設定方法など、Webman を使用してレスポンシブ Web サイト開発を行うためのヒントをいくつか紹介します。

React を使用して応答性の高いバックエンド管理システムを開発する方法 インターネットの急速な発展に伴い、日々の業務を処理するために効率的で柔軟で管理が容易なバックエンド管理システムを必要とする企業や組織が増えています。現在最も人気のある JavaScript ライブラリの 1 つである React は、ユーザー インターフェイスを構築するための簡潔で効率的かつ保守しやすい方法を提供します。この記事では、React を使用して応答性の高いバックエンド管理システムを開発する方法と、具体的なコード例を紹介します。まず React プロジェクトを作成します

Layui を使用してレスポンシブなカレンダー機能を実装する方法 1. はじめに Web 開発において、カレンダー機能は一般的な要件の 1 つです。 Layui は、カレンダー コンポーネントを含む豊富な UI コンポーネントを提供する優れたフロントエンド フレームワークです。この記事では、Layuiを使ってレスポンシブカレンダー機能を実装する方法と具体的なコード例を紹介します。 2. HTML 構造 カレンダー機能を実装するには、まず適切な HTML 構造を作成する必要があります。 div 要素を最も外側のコンテナとして使用し、その中で使用できます。
